summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt8
-rw-r--r--core/api/system-current.txt6
-rw-r--r--core/api/test-current.txt5
-rw-r--r--core/java/Android.bp2
-rw-r--r--core/java/android/app/ActivityThread.java18
-rw-r--r--core/java/android/app/INotificationManager.aidl5
-rw-r--r--core/java/android/app/Notification.java8
-rw-r--r--core/java/android/app/NotificationChannel.java25
-rw-r--r--core/java/android/app/NotificationManager.java29
-rw-r--r--core/java/android/app/PropertyInvalidatedCache.java20
-rw-r--r--core/java/android/app/StatusBarManager.java36
-rw-r--r--core/java/android/app/UiAutomation.java46
-rw-r--r--core/java/android/app/notification.aconfig7
-rw-r--r--core/java/android/app/supervision/ISupervisionManager.aidl2
-rw-r--r--core/java/android/app/supervision/SupervisionManager.java46
-rw-r--r--core/java/android/companion/virtual/flags/flags.aconfig7
-rw-r--r--core/java/android/content/Context.java5
-rw-r--r--core/java/android/content/pm/PackageParser.java18
-rw-r--r--core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java33
-rw-r--r--core/java/android/hardware/biometrics/BiometricConstants.java11
-rw-r--r--core/java/android/hardware/biometrics/BiometricManager.java2
-rw-r--r--core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java38
-rw-r--r--core/java/android/hardware/biometrics/flags.aconfig8
-rw-r--r--core/java/android/hardware/contexthub/HubEndpoint.java44
-rw-r--r--core/java/android/hardware/display/DisplayTopology.java133
-rw-r--r--core/java/android/hardware/display/DisplayTopologyGraph.java19
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl6
-rw-r--r--core/java/android/hardware/input/InputManagerGlobal.java39
-rw-r--r--core/java/android/inputmethodservice/NavigationBarController.java22
-rw-r--r--core/java/android/inputmethodservice/navigationbar/NavigationBarView.java40
-rw-r--r--core/java/android/os/BatteryUsageStats.java11
-rw-r--r--core/java/android/os/BatteryUsageStatsQuery.java25
-rw-r--r--core/java/android/os/CombinedMessageQueue/MessageQueue.java50
-rw-r--r--core/java/android/os/ConcurrentMessageQueue/MessageQueue.java14
-rw-r--r--core/java/android/os/LegacyMessageQueue/MessageQueue.java36
-rw-r--r--core/java/android/os/TestLooperManager.java31
-rw-r--r--core/java/android/os/UserManager.java8
-rw-r--r--core/java/android/os/flags.aconfig7
-rw-r--r--core/java/android/service/contextualsearch/OWNERS1
-rw-r--r--core/java/android/service/notification/Adjustment.java5
-rw-r--r--core/java/android/service/notification/NotificationAssistantService.java12
-rw-r--r--core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java53
-rw-r--r--core/java/android/view/Choreographer.java2
-rw-r--r--core/java/android/view/IWindowManager.aidl8
-rw-r--r--core/java/android/view/InsetsController.java23
-rw-r--r--core/java/android/view/NotificationHeaderView.java49
-rw-r--r--core/java/android/view/ViewRootImpl.java56
-rw-r--r--core/java/android/view/ViewRootInsetsControllerHost.java7
-rw-r--r--core/java/android/view/contentcapture/ChildContentCaptureSession.java4
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java13
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java5
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java136
-rw-r--r--core/java/android/view/contentcapture/flags/content_capture_flags.aconfig11
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java3
-rw-r--r--core/java/android/view/inputmethod/flags.aconfig9
-rw-r--r--core/java/android/widget/RemoteViews.java101
-rw-r--r--core/java/android/window/DesktopExperienceFlags.java35
-rw-r--r--core/java/android/window/DesktopModeFlags.java37
-rw-r--r--core/java/android/window/WindowContainerTransaction.java725
-rw-r--r--core/java/android/window/flags/device_state_auto_rotate_setting.aconfig22
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig17
-rw-r--r--core/java/android/window/flags/responsible_apis.aconfig7
-rw-r--r--core/java/com/android/internal/app/IntentForwarderActivity.java27
-rw-r--r--core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java4
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistory.java51
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl6
-rw-r--r--core/java/com/android/internal/widget/ConversationLayout.java29
-rw-r--r--core/java/com/android/internal/widget/MessagingData.java13
-rw-r--r--core/java/com/android/internal/widget/MessagingMessage.java2
-rw-r--r--core/java/com/android/internal/widget/NotificationProgressBar.java6
-rw-r--r--core/java/com/android/internal/widget/NotificationProgressDrawable.java7
-rw-r--r--core/java/com/android/internal/widget/remotecompose/accessibility/CoreDocumentAccessibility.java7
-rw-r--r--core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeAccessibilityRegistrar.java4
-rw-r--r--core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java4
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java10
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/Operations.java16
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java116
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/RemoteContextAware.java31
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java219
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java244
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java4
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java232
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java185
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionDefine.java168
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java2
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java10
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java17
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java36
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java24
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java10
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java16
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java16
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java24
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java72
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java9
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java34
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java31
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java34
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java34
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java38
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java27
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java11
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java25
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java16
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java16
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java5
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java51
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java11
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionInModifierOperation.java109
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java10
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java31
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java53
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java7
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java15
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java13
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java38
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java6
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java24
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java9
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java21
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java38
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java23
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java12
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java12
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java12
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java12
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java53
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java7
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java23
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java21
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/paint/TextPaint.java199
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java8
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/utilities/DataMap.java18
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java20
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java25
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java24
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java6
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java122
-rw-r--r--core/java/com/android/internal/widget/remotecompose/core/serialize/Serializable.java27
-rw-r--r--core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java8
-rw-r--r--core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java2
-rw-r--r--core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java6
-rw-r--r--core/jni/android_app_PropertyInvalidatedCache.h12
-rw-r--r--core/jni/android_hardware_display_DisplayTopology.cpp22
-rw-r--r--core/proto/android/service/appwidget.proto1
-rw-r--r--core/res/res/values-ar/strings.xml14
-rw-r--r--core/res/res/values-gl/strings.xml2
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-mk/strings.xml2
-rw-r--r--core/res/res/values-mn/strings.xml2
-rw-r--r--core/res/res/values-mr/strings.xml2
-rw-r--r--core/res/res/values-sl/strings.xml2
-rw-r--r--core/res/res/values-ta/strings.xml2
-rw-r--r--core/res/res/values-te/strings.xml2
-rw-r--r--core/res/res/values-zh-rCN/strings.xml4
-rw-r--r--core/tests/coretests/src/android/app/NotificationManagerTest.java44
-rw-r--r--core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java51
-rw-r--r--core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt2
-rw-r--r--core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt245
-rw-r--r--core/tests/coretests/src/android/view/ViewRootImplTest.java3
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java2
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java61
-rw-r--r--core/tests/coretests/src/android/widget/RemoteViewsTest.java131
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java50
-rw-r--r--libs/WindowManager/Shell/aconfig/multitasking.aconfig7
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_windowing_education_horizontal_arrow_tooltip.xml (renamed from libs/WindowManager/Shell/res/layout/desktop_windowing_education_left_arrow_tooltip.xml)3
-rw-r--r--libs/WindowManager/Shell/res/values/ids.xml5
-rw-r--r--libs/WindowManager/Shell/res/values/strings.xml22
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/PhysicsAnimator.kt5
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/WindowAnimator.kt2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt57
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java44
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt95
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt101
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeMouse.kt12
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeStylus.kt12
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeTouchpad.kt12
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt27
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt59
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt52
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt87
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java30
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/WindowAnimatorTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt4
-rw-r--r--media/java/android/media/AudioFormat.java8
-rw-r--r--media/java/android/media/OWNERS1
-rw-r--r--media/java/android/media/audio/common/AidlConversion.java4
-rw-r--r--media/java/android/media/audiofx/AudioEffect.java14
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java24
-rw-r--r--packages/ExtShared/Android.bp1
-rw-r--r--packages/ExtShared/proguard.proguard4
-rw-r--r--packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml2
-rw-r--r--packages/SettingsLib/TopIntroPreference/res/layout/settingslib_expressive_top_intro.xml3
-rw-r--r--packages/SettingsLib/res/drawable/dialog_btn_filled.xml2
-rw-r--r--packages/SettingsLib/res/drawable/dialog_btn_outline.xml2
-rw-r--r--packages/SettingsLib/res/layout/dialog_with_icon.xml2
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-iw/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-or/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-te/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/res/values/styles.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java5
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java47
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java2
-rw-r--r--packages/Shell/Android.bp2
-rw-r--r--packages/Shell/AndroidManifest.xml7
-rw-r--r--packages/SystemUI/AndroidManifest.xml11
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml2
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/res/values-pt/strings.xml2
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig41
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java4
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt4
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt4
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt8
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt15
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt30
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt3
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/LogUtil.kt32
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt55
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt48
-rw-r--r--packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSecureSettingsRepository.kt5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt152
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt74
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt130
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt8
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt12
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt62
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt79
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt98
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt27
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt40
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt154
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelTest.kt70
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt49
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelTest.kt70
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt50
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt46
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelTest.kt66
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt38
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardWindowBlurTestUtilKosmos.kt15
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt41
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelTest.kt66
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelTest.kt78
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt40
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt39
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelTest.kt35
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaDataRepositoryTest.kt25
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt23
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaRecommendationsInteractorTest.kt28
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt84
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java58
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/OWNERS1
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/NavBarHelperTest.java8
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarButtonTest.java4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarInflaterViewTest.java4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java87
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTransitionsTest.java4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/buttons/KeyButtonViewTest.java4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModelTest.kt20
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayContentViewModelTest.kt5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java15
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt81
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorTest.kt17
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt16
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/MediaInRowInLandscapeViewModelTest.kt13
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QSColumnsViewModelTest.kt17
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractorTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt35
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModelTest.kt20
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayContentViewModelTest.kt10
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt9
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt15
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt25
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt24
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt71
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt15
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt25
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModelTest.kt7
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt18
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt11
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt54
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt39
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt52
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt11
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt214
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt71
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt33
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt11
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt39
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt16
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockLogger.kt118
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt12
-rw-r--r--packages/SystemUI/res-keyguard/layout/bouncer_message_view.xml4
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml2
-rw-r--r--packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml1
-rw-r--r--packages/SystemUI/res/layout/low_light_clock_dream.xml39
-rw-r--r--packages/SystemUI/res/layout/media_output_list_item_advanced.xml21
-rw-r--r--packages/SystemUI/res/layout/privacy_dialog_item_v2.xml1
-rw-r--r--packages/SystemUI/res/layout/shade_carrier.xml2
-rw-r--r--packages/SystemUI/res/layout/shade_carrier_group.xml2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml33
-rw-r--r--packages/SystemUI/res/values-am/strings.xml33
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml27
-rw-r--r--packages/SystemUI/res/values-as/strings.xml33
-rw-r--r--packages/SystemUI/res/values-az/strings.xml33
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml32
-rw-r--r--packages/SystemUI/res/values-be/strings.xml30
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml33
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml33
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml32
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml33
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml26
-rw-r--r--packages/SystemUI/res/values-da/strings.xml33
-rw-r--r--packages/SystemUI/res/values-de/strings.xml33
-rw-r--r--packages/SystemUI/res/values-el/strings.xml32
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml33
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml25
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml33
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml33
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml35
-rw-r--r--packages/SystemUI/res/values-es/strings.xml33
-rw-r--r--packages/SystemUI/res/values-et/strings.xml35
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml35
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml32
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml33
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml32
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml30
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml33
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml33
-rw-r--r--packages/SystemUI/res/values-gu/tiles_states_strings.xml2
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml37
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml32
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml34
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml32
-rw-r--r--packages/SystemUI/res/values-in/strings.xml33
-rw-r--r--packages/SystemUI/res/values-is/strings.xml33
-rw-r--r--packages/SystemUI/res/values-it/strings.xml33
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml49
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml32
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml32
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml33
-rw-r--r--packages/SystemUI/res/values-km/strings.xml33
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml32
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml35
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml33
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml32
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml30
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml33
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml33
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml32
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml37
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml34
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml32
-rw-r--r--packages/SystemUI/res/values-my/strings.xml30
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml33
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml33
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml32
-rw-r--r--packages/SystemUI/res/values-or/strings.xml33
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml32
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml33
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml33
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml32
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml33
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml33
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml33
-rw-r--r--packages/SystemUI/res/values-si/strings.xml33
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml33
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml30
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml30
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml32
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml33
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml33
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml33
-rw-r--r--packages/SystemUI/res/values-te/strings.xml32
-rw-r--r--packages/SystemUI/res/values-th/strings.xml30
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml32
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml30
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml32
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml30
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml33
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml32
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml33
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml33
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml33
-rw-r--r--packages/SystemUI/res/values/colors.xml5
-rw-r--r--packages/SystemUI/res/values/dimens.xml16
-rw-r--r--packages/SystemUI/res/values/strings.xml6
-rw-r--r--packages/SystemUI/res/values/styles.xml8
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/ILauncherProxy.aidl (renamed from packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl)4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java34
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt99
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/UdfpsTouchOverlayBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/brightness/data/repository/BrightnessPolicyRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/domain/interactor/PackageChangeInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java101
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalTutorialRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/development/domain/interactor/BuildNumberInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricSettingsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/homecontrols/service/RemoteHomeControlsDataSourceDelegator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/homecontrols/system/domain/interactor/HomeControlsComponentInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/AccessibilityShortcutsSource.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt168
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubBlurComponent.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubTransitionModule.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DevicePostureInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt2
-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/LightRevealScrimInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt67
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubBlurProvider.kt40
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubTransition.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/InWindowLauncherUnlockAnimationManager.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultUdfpsAccessibilityOverlaySection.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt124
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerUdfpsIconViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModel.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSettingsMenuViewModel.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAlternateBouncerTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToDozingTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModel.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludingAppDeviceEntryMessageViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModel.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/echo/LogcatEchoTrackerDebug.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt137
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/ChargingStatusProvider.java258
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java137
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockAnimationProvider.java127
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightDisplayController.kt (renamed from packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromNotificationsShadeToQuickSettingsShadeTransition.kt)14
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightDockEvent.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightLogger.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.java133
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightLog.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java150
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaDataRepository.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImpl.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt45
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt53
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaControlDrawables.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/model/SysUiState.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java106
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java100
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManager.kt81
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileServiceInteractor.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java (renamed from packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java)126
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt51
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/ScrimStartable.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/BaseShadeControllerImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt131
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelper.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NmSummarizationUiFlag.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/SingleLineViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationBundleUi.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManager.kt130
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt247
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticRowListener.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java88
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt86
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/GestureRecognizerAdapter.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/settings/repository/UserAwareSettingsRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/ui/AnimatedValue.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioSharingStreamSliderViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt57
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt23
-rw-r--r--packages/SystemUI/src/com/google/android/systemui/lowlightclock/LowLightClockDreamService.java161
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/AmbientLightModeMonitorTest.kt110
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ChargingStatusProviderTest.java226
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/DirectBootConditionTest.kt102
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ForceLowLightConditionTest.java110
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockAnimationProviderTest.kt75
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockDreamServiceTest.java160
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightConditionTest.java143
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightMonitorTest.java183
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ScreenSaverEnabledConditionTest.java108
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImplTest.kt69
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt207
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt45
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManagerTest.kt40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt)54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt70
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt32
-rw-r--r--packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt92
-rw-r--r--packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryKosmos.kt12
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt6
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt33
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/GlanceableHubBlurComponentFactoryKosmos.kt37
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/FakeGlanceableHubTransition.kt23
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt6
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelKosmos.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelKosmos.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelKosmos.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelKosmos.kt1
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelKosmos.kt1
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt23
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt42
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerKosmos.kt36
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeZenModeController.java27
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt14
-rw-r--r--packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/VcnManagementService.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java3
-rw-r--r--packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java3
-rw-r--r--packages/VpnDialogs/res/values-in/strings.xml2
-rwxr-xr-xravenwood/scripts/add-annotations.sh84
-rwxr-xr-xravenwood/scripts/pta-framework.sh2
-rw-r--r--ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt7
-rw-r--r--ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt7
-rw-r--r--ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt24
-rw-r--r--ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt27
-rw-r--r--ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MapOptions.kt95
-rw-r--r--ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MarkMethodHandler.kt197
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java3
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java73
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java8
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java76
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java45
-rw-r--r--services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java27
-rw-r--r--services/core/java/com/android/server/DockObserver.java17
-rw-r--r--services/core/java/com/android/server/DockObserverInternal.java25
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java19
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java16
-rw-r--r--services/core/java/com/android/server/am/flags.aconfig11
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java1
-rw-r--r--services/core/java/com/android/server/biometrics/AuthService.java7
-rw-r--r--services/core/java/com/android/server/biometrics/AuthSession.java3
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java5
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java10
-rw-r--r--services/core/java/com/android/server/display/feature/display_flags.aconfig8
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginManager.java40
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginStorage.java221
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginType.java10
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginsProvider.java4
-rw-r--r--services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java59
-rw-r--r--services/core/java/com/android/server/infra/AbstractMasterSystemService.java50
-rw-r--r--services/core/java/com/android/server/infra/AbstractPerUserSystemService.java2
-rw-r--r--services/core/java/com/android/server/infra/OWNERS1
-rw-r--r--services/core/java/com/android/server/input/InputGestureManager.java2
-rw-r--r--services/core/java/com/android/server/input/InputManagerInternal.java4
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java17
-rw-r--r--services/core/java/com/android/server/input/KeyboardLayoutManager.java35
-rw-r--r--services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java20
-rw-r--r--services/core/java/com/android/server/media/projection/MediaProjectionStopController.java32
-rw-r--r--services/core/java/com/android/server/media/quality/MediaQualityService.java482
-rw-r--r--services/core/java/com/android/server/notification/NotificationDelegate.java11
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java407
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java4
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java51
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerSettings.java46
-rw-r--r--services/core/java/com/android/server/pinner/PinnerService.java10
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java18
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java8
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java27
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java16
-rw-r--r--services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayAreaPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java21
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java19
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java31
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java34
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerService.java249
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java7
-rw-r--r--services/supervision/java/com/android/server/supervision/SupervisionService.java155
-rw-r--r--services/supervision/java/com/android/server/supervision/SupervisionServiceShellCommand.java12
-rw-r--r--services/supervision/java/com/android/server/supervision/SupervisionUserData.java2
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt17
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt89
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java45
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java43
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java67
-rw-r--r--services/tests/servicestests/AndroidManifest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java121
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java107
-rw-r--r--services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java86
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java28
-rw-r--r--services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt42
-rw-r--r--services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java4
-rw-r--r--services/tests/uiservicestests/Android.bp1
-rw-r--r--services/tests/uiservicestests/AndroidManifest.xml2
-rw-r--r--services/tests/uiservicestests/src/android/app/ExampleActivity.java20
-rw-r--r--services/tests/uiservicestests/src/android/app/NotificationManagerZenTest.java284
-rw-r--r--services/tests/uiservicestests/src/android/app/NotificationSystemUtil.java71
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java134
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java471
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java47
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java39
-rw-r--r--telecomm/java/android/telecom/CallerInfoAsyncQuery.java2
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java2
-rw-r--r--telephony/java/com/android/internal/telephony/util/WorkerThread.java130
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt7
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt7
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt7
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt11
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt17
-rw-r--r--tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt8
-rw-r--r--tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt5
-rw-r--r--tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt37
-rw-r--r--tests/testables/src/android/testing/OWNERS2
-rw-r--r--tests/testables/src/android/testing/TestableLooper.java6
-rw-r--r--tests/utils/testutils/java/android/os/test/OWNERS3
-rw-r--r--tests/utils/testutils/java/android/os/test/TestLooper.java12
1048 files changed, 19728 insertions, 7684 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 3883a9667355..17e7d7a258d8 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11134,6 +11134,7 @@ package android.content {
field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
field public static final String TELEPHONY_SERVICE = "phone";
field public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
+ field public static final String TETHERING_SERVICE = "tethering";
field public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification";
field public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
field @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public static final String TV_AD_SERVICE = "tv_ad";
@@ -19345,7 +19346,7 @@ package android.hardware.biometrics {
public class BiometricManager {
method @Deprecated @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate();
method @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate(int);
- method @FlaggedApi("android.hardware.biometrics.last_authentication_time") @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public long getLastAuthenticationTime(int);
+ method @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public long getLastAuthenticationTime(int);
method @NonNull @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public android.hardware.biometrics.BiometricManager.Strings getStrings(int);
field public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1; // 0x1
field @FlaggedApi("android.hardware.biometrics.identity_check_api") public static final int BIOMETRIC_ERROR_IDENTITY_CHECK_NOT_ACTIVE = 20; // 0x14
@@ -19353,7 +19354,7 @@ package android.hardware.biometrics {
field @FlaggedApi("android.hardware.biometrics.identity_check_api") public static final int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = 21; // 0x15
field public static final int BIOMETRIC_ERROR_NO_HARDWARE = 12; // 0xc
field public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; // 0xf
- field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
+ field public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
field public static final int BIOMETRIC_SUCCESS = 0; // 0x0
}
@@ -19406,7 +19407,7 @@ package android.hardware.biometrics {
field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
field public static final int BIOMETRIC_ERROR_USER_CANCELED = 10; // 0xa
field public static final int BIOMETRIC_ERROR_VENDOR = 8; // 0x8
- field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
+ field public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
}
public abstract static class BiometricPrompt.AuthenticationCallback {
@@ -21749,6 +21750,7 @@ package android.media {
field public static final int CHANNEL_IN_X_AXIS = 2048; // 0x800
field public static final int CHANNEL_IN_Y_AXIS = 4096; // 0x1000
field public static final int CHANNEL_IN_Z_AXIS = 8192; // 0x2000
+ field @FlaggedApi("android.media.audio.sony_360ra_mpegh_3d_format") public static final int CHANNEL_OUT_13POINT0 = 30136348; // 0x1cbd81c
field public static final int CHANNEL_OUT_5POINT1 = 252; // 0xfc
field public static final int CHANNEL_OUT_5POINT1POINT2 = 3145980; // 0x3000fc
field public static final int CHANNEL_OUT_5POINT1POINT4 = 737532; // 0xb40fc
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 8a5276c1ce08..41f286245d8d 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3800,7 +3800,6 @@ package android.content {
field public static final String STATS_MANAGER = "stats";
field public static final String SYSTEM_CONFIG_SERVICE = "system_config";
field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
- field public static final String TETHERING_SERVICE = "tethering";
field @FlaggedApi("com.android.net.thread.platform.flags.thread_enabled_platform") public static final String THREAD_NETWORK_SERVICE = "thread_network";
field public static final String TIME_MANAGER_SERVICE = "time_manager";
field public static final String TRANSLATION_MANAGER_SERVICE = "translation";
@@ -13481,6 +13480,7 @@ package android.service.notification {
method public final void unsnoozeNotification(@NonNull String);
field public static final String ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS = "android.service.notification.action.NOTIFICATION_ASSISTANT_DETAIL_SETTINGS";
field @FlaggedApi("android.service.notification.notification_classification") public static final String ACTION_NOTIFICATION_ASSISTANT_FEEDBACK_SETTINGS = "android.service.notification.action.NOTIFICATION_ASSISTANT_FEEDBACK_SETTINGS";
+ field @FlaggedApi("android.app.nm_summarization") public static final String EXTRA_NOTIFICATION_ADJUSTMENT = "android.service.notification.extra.NOTIFICATION_ADJUSTMENT";
field @FlaggedApi("android.service.notification.notification_classification") public static final String EXTRA_NOTIFICATION_KEY = "android.service.notification.extra.NOTIFICATION_KEY";
field public static final String FEEDBACK_RATING = "feedback.rating";
field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -16042,7 +16042,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
- method @FlaggedApi("com.android.internal.telephony.flags.enable_identifier_disclosure_transparency") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCellularIdentifierDisclosureNotificationsEnabled();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCellularIdentifierDisclosureNotificationsEnabled();
method public boolean isDataConnectivityPossible();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
method @FlaggedApi("com.android.internal.telephony.flags.use_oem_domain_selection_service") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDomainSelectionSupported();
@@ -16093,7 +16093,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
- method @FlaggedApi("com.android.internal.telephony.flags.enable_identifier_disclosure_transparency") @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setEnableCellularIdentifierDisclosureNotifications(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setEnableCellularIdentifierDisclosureNotifications(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult setIccLockEnabled(boolean, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabled(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index e2fe5062d356..7c1c86823110 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -478,8 +478,8 @@ package android.app {
method public void destroy();
method @NonNull public java.util.Set<java.lang.String> getAdoptedShellPermissions();
method @Deprecated public boolean grantRuntimePermission(String, String, android.os.UserHandle);
- method public boolean injectInputEvent(@NonNull android.view.InputEvent, boolean, boolean);
- method public void injectInputEventToInputFilter(@NonNull android.view.InputEvent);
+ method @Deprecated @FlaggedApi("com.android.input.flags.deprecate_uiautomation_input_injection") public boolean injectInputEvent(@NonNull android.view.InputEvent, boolean, boolean);
+ method @Deprecated @FlaggedApi("com.android.input.flags.deprecate_uiautomation_input_injection") public void injectInputEventToInputFilter(@NonNull android.view.InputEvent);
method public boolean isNodeInCache(@NonNull android.view.accessibility.AccessibilityNodeInfo);
method public void removeOverridePermissionState(int, @NonNull String);
method @Deprecated public boolean revokeRuntimePermission(String, String, android.os.UserHandle);
@@ -2140,6 +2140,7 @@ package android.media.audiofx {
method public void setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener);
method public static byte[] shortToByteArray(short);
field public static final java.util.UUID EFFECT_TYPE_NULL;
+ field @NonNull public static final java.util.UUID EFFECT_TYPE_SPATIALIZER;
}
public static class AudioEffect.Descriptor {
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 1e97d4f12836..1ad247e24bc0 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -87,7 +87,7 @@ release_package_messagequeue_implementation_srcs {
release_package_messagequeue_implementation: {
srcs: ["android/os/%s"],
conditions_default: {
- srcs: ["android/os/LegacyMessageQueue/MessageQueue.java"],
+ srcs: ["android/os/CombinedMessageQueue/MessageQueue.java"],
},
},
},
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7b9ec4a7821e..2d7ed46fe64a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3959,10 +3959,20 @@ public final class ActivityThread extends ClientTransactionHandler
/** Converts a process state to a VM process state. */
private static int toVmProcessState(int processState) {
- final int state = ActivityManager.isProcStateJankPerceptible(processState)
- ? VM_PROCESS_STATE_JANK_PERCEPTIBLE
- : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
- return state;
+ if (ActivityManager.isProcStateJankPerceptible(processState)) {
+ return VM_PROCESS_STATE_JANK_PERCEPTIBLE;
+ }
+
+ if (Flags.jankPerceptibleNarrow()) {
+ // Unlike other persistent processes, system server is often on
+ // the critical path for application startup. Mark it explicitly
+ // as jank perceptible regardless of processState.
+ if (isSystem()) {
+ return VM_PROCESS_STATE_JANK_PERCEPTIBLE;
+ }
+ }
+
+ return VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
}
/** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 8fa2362139a1..3fb08224b9db 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -114,7 +114,6 @@ interface INotificationManager
NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, String conversationId, boolean includeDeleted);
void deleteNotificationChannel(String pkg, String channelId);
ParceledListSlice getNotificationChannels(String callingPkg, String targetPkg, int userId);
- ParceledListSlice getOrCreateNotificationChannels(String callingPkg, String targetPkg, int userId, boolean createPrefsIfNeeded);
ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getDeletedChannelCount(String pkg, int uid);
@@ -271,8 +270,8 @@ interface INotificationManager
int[] getAllowedAdjustmentKeyTypes();
void setAssistantAdjustmentKeyTypeState(int type, boolean enabled);
- String[] getTypeAdjustmentDeniedPackages();
- void setTypeAdjustmentForPackageState(String pkg, boolean enabled);
+ boolean isAdjustmentSupportedForPackage(String key, String pkg);
+ void setAdjustmentSupportedForPackage(String key, String pkg, boolean enabled);
// TODO: b/389918945 - Remove once nm_binder_perf flags are going to Nextfood.
void incrementCounter(String metricId);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 35308ee43dea..ba4914954223 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1772,6 +1772,11 @@ public class Notification implements Parcelable
*/
public static final String EXTRA_FOREGROUND_APPS = "android.foregroundApps";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_SUMMARIZED_CONTENT = "android.summarization";
+
@UnsupportedAppUsage
private Icon mSmallIcon;
@UnsupportedAppUsage
@@ -4421,8 +4426,7 @@ public class Notification implements Parcelable
* notification) out of the actions in this notification.
*/
public @NonNull List<Notification.Action> getContextualActions() {
- if (actions == null) return Collections.emptyList();
-
+ if (actions == null || isPromotedOngoing()) return Collections.emptyList();
List<Notification.Action> contextualActions = new ArrayList<>();
for (Notification.Action action : actions) {
if (action.isContextual()) {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 73d26b834497..c6f008c46f99 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -15,6 +15,10 @@
*/
package android.app;
+import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION;
+import static android.service.notification.Adjustment.TYPE_NEWS;
+import static android.service.notification.Adjustment.TYPE_PROMOTION;
+import static android.service.notification.Adjustment.TYPE_SOCIAL_MEDIA;
import static android.service.notification.Flags.FLAG_NOTIFICATION_CONVERSATION_CHANNEL_MANAGEMENT;
import android.annotation.FlaggedApi;
@@ -37,6 +41,7 @@ import android.os.VibrationEffect;
import android.os.vibrator.persistence.VibrationXmlParser;
import android.os.vibrator.persistence.VibrationXmlSerializer;
import android.provider.Settings;
+import android.service.notification.Adjustment;
import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
import android.util.Log;
@@ -1606,6 +1611,26 @@ public final class NotificationChannel implements Parcelable {
return sb.toString();
}
+ /**
+ * Get the reserved bundle channel ID for an Adjustment type
+ * @param the Adjustment type
+ * @return the channel ID, or null if type is invalid
+ * @hide
+ */
+ public static @Nullable String getChannelIdForBundleType(@Adjustment.Types int type) {
+ switch (type) {
+ case TYPE_CONTENT_RECOMMENDATION:
+ return RECS_ID;
+ case TYPE_NEWS:
+ return NEWS_ID;
+ case TYPE_PROMOTION:
+ return PROMOTIONS_ID;
+ case TYPE_SOCIAL_MEDIA:
+ return SOCIAL_MEDIA_ID;
+ }
+ return null;
+ }
+
public static final @android.annotation.NonNull Creator<NotificationChannel> CREATOR =
new Creator<NotificationChannel>() {
@Override
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 1e1ec602d0a2..6e31779f2fb3 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1264,8 +1264,7 @@ public class NotificationManager {
mNotificationChannelListCache.query(new NotificationChannelQuery(
mContext.getOpPackageName(),
mContext.getPackageName(),
- mContext.getUserId(),
- true))); // create (default channel) if needed
+ mContext.getUserId())));
} else {
INotificationManager service = service();
try {
@@ -1293,8 +1292,7 @@ public class NotificationManager {
mNotificationChannelListCache.query(new NotificationChannelQuery(
mContext.getOpPackageName(),
mContext.getPackageName(),
- mContext.getUserId(),
- true))); // create (default channel) if needed
+ mContext.getUserId())));
} else {
INotificationManager service = service();
try {
@@ -1320,8 +1318,7 @@ public class NotificationManager {
return mNotificationChannelListCache.query(new NotificationChannelQuery(
mContext.getOpPackageName(),
mContext.getPackageName(),
- mContext.getUserId(),
- false));
+ mContext.getUserId()));
} else {
INotificationManager service = service();
try {
@@ -1461,8 +1458,8 @@ public class NotificationManager {
public List<NotificationChannel> apply(NotificationChannelQuery query) {
INotificationManager service = service();
try {
- return service.getOrCreateNotificationChannels(query.callingPkg,
- query.targetPkg, query.userId, query.createIfNeeded).getList();
+ return service.getNotificationChannels(query.callingPkg,
+ query.targetPkg, query.userId).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1490,8 +1487,7 @@ public class NotificationManager {
private record NotificationChannelQuery(
String callingPkg,
String targetPkg,
- int userId,
- boolean createIfNeeded) {}
+ int userId) {}
/**
* @hide
@@ -2175,19 +2171,6 @@ public class NotificationManager {
/**
* @hide
*/
- @FlaggedApi(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- public void setTypeAdjustmentForPackageState(@NonNull String pkg, boolean enabled) {
- INotificationManager service = service();
- try {
- service.setTypeAdjustmentForPackageState(pkg, enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
public List<String> getEnabledNotificationListenerPackages() {
INotificationManager service = service();
try {
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 660d88007c9a..e9b2ffcdf4cc 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -2321,12 +2321,14 @@ public class PropertyInvalidatedCache<Query, Result> {
@GuardedBy("mLock")
private int mBlockHash = 0;
- // The number of nonces that the native layer can hold. This is maintained for debug and
- // logging.
- private final int mMaxNonce;
+ // The number of nonces that the native layer can hold. This is maintained for debug,
+ // logging, and testing.
+ @VisibleForTesting
+ public final int mMaxNonce;
// The size of the native byte block.
- private final int mMaxByte;
+ @VisibleForTesting
+ public final int mMaxByte;
/** @hide */
@VisibleForTesting
@@ -2483,18 +2485,20 @@ public class PropertyInvalidatedCache<Query, Result> {
}
}
- static final AtomicLong sStoreCount = new AtomicLong();
-
-
// Add a string to the local copy of the block and write the block to shared memory.
// Return the index of the new string. If the string has already been recorded, the
- // shared memory is not updated but the index of the existing string is returned.
+ // shared memory is not updated but the index of the existing string is returned. Only
+ // mMaxNonce strings can be stored; if mMaxNonce strings have already been allocated,
+ // the method throws.
public int storeName(@NonNull String str) {
synchronized (mLock) {
Integer handle = mStringHandle.get(str);
if (handle == null) {
throwIfImmutable();
throwIfBadString(str);
+ if (mHighestIndex + 1 >= mMaxNonce) {
+ throw new RuntimeException("nonce limit exceeded");
+ }
byte[] block = new byte[mMaxByte];
nativeGetByteBlock(mPtr, 0, block);
appendStringToMapLocked(str, block);
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 039f7b6a86ba..01868cc601fe 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -205,31 +205,31 @@ public class StatusBarManager {
*
* @hide
*/
- public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0;
+ public static final int NAVBAR_BACK_DISMISS_IME = 1 << 0;
/**
* The IME is visible.
*
* @hide
*/
- public static final int NAVIGATION_HINT_IME_VISIBLE = 1 << 1;
+ public static final int NAVBAR_IME_VISIBLE = 1 << 1;
/**
* The IME Switcher button is visible. This only takes effect while the IME is visible.
*
* @hide
*/
- public static final int NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE = 1 << 2;
+ public static final int NAVBAR_IME_SWITCHER_BUTTON_VISIBLE = 1 << 2;
/**
- * Navigation bar flags related to the IME state.
+ * Navigation bar state flags.
*
* @hide
*/
- @IntDef(flag = true, prefix = { "NAVIGATION_HINT_" }, value = {
- NAVIGATION_HINT_BACK_ALT,
- NAVIGATION_HINT_IME_VISIBLE,
- NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE,
+ @IntDef(flag = true, prefix = { "NAVBAR_" }, value = {
+ NAVBAR_BACK_DISMISS_IME,
+ NAVBAR_IME_VISIBLE,
+ NAVBAR_IME_SWITCHER_BUTTON_VISIBLE,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface NavigationHint {}
+ public @interface NavbarFlags {}
/** @hide */
public static final int WINDOW_STATUS_BAR = 1;
@@ -1355,18 +1355,18 @@ public class StatusBarManager {
/** @hide */
@NonNull
- public static String navigationHintsToString(@NavigationHint int hints) {
- final var hintStrings = new ArrayList<String>();
- if ((hints & NAVIGATION_HINT_BACK_ALT) != 0) {
- hintStrings.add("NAVIGATION_HINT_BACK_ALT");
+ public static String navbarFlagsToString(@NavbarFlags int flags) {
+ final var flagStrings = new ArrayList<String>();
+ if ((flags & NAVBAR_BACK_DISMISS_IME) != 0) {
+ flagStrings.add("NAVBAR_BACK_DISMISS_IME");
}
- if ((hints & NAVIGATION_HINT_IME_VISIBLE) != 0) {
- hintStrings.add("NAVIGATION_HINT_IME_VISIBLE");
+ if ((flags & NAVBAR_IME_VISIBLE) != 0) {
+ flagStrings.add("NAVBAR_IME_VISIBLE");
}
- if ((hints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0) {
- hintStrings.add("NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE");
+ if ((flags & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0) {
+ flagStrings.add("NAVBAR_IME_SWITCHER_BUTTON_VISIBLE");
}
- return String.join(" | ", hintStrings);
+ return String.join(" | ", flagStrings);
}
/** @hide */
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 063055eb4917..ba8fbc121e8d 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -18,6 +18,8 @@ package android.app;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.input.flags.Flags.FLAG_DEPRECATE_UIAUTOMATION_INPUT_INJECTION;
+
import android.accessibilityservice.AccessibilityGestureEvent;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityService.Callbacks;
@@ -26,6 +28,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.MagnificationConfig;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -108,7 +111,10 @@ import java.util.concurrent.TimeoutException;
* client should be using a higher-level library or implement high-level functions.
* For example, performing a tap on the screen requires construction and injecting
* of a touch down and up events which have to be delivered to the system by a
- * call to {@link #injectInputEvent(InputEvent, boolean)}.
+ * call to {@link #injectInputEvent(InputEvent, boolean)}. <strong>Note:</strong> For CTS tests, it
+ * is preferable to inject input events using uinput (com.android.cts.input.UinputDevice) or hid
+ * devices (com.android.cts.input.HidDevice). Alternatively, use InjectInputInProcess
+ * (com.android.cts.input.InjectInputInProcess) for in-process injection.
* </p>
* <p>
* The APIs exposed by this class operate across applications enabling a client
@@ -122,7 +128,7 @@ public final class UiAutomation {
private static final String LOG_TAG = UiAutomation.class.getSimpleName();
private static final boolean DEBUG = false;
- private static final boolean VERBOSE = false;
+ private static final boolean VERBOSE = Build.IS_DEBUGGABLE;
private static final int CONNECTION_ID_UNDEFINED = -1;
@@ -957,9 +963,17 @@ public final class UiAutomation {
* <strong>Note:</strong> It is caller's responsibility to recycle the event.
* </p>
*
- * @param event The event to inject.
- * @param sync Whether to inject the event synchronously.
- * @return Whether event injection succeeded.
+ * <p>
+ * <strong>Note:</strong> Avoid this method when injecting input events in CTS tests. Instead
+ * use uinput (com.android.cts.input.UinputDevice)
+ * or hid devices (com.android.cts.input.HidDevice), as they provide a more accurate simulation
+ * of real device behavior. Alternatively, InjectInputInProcess
+ * (com.android.cts.input.InjectInputProcess) can be used for in-process injection.
+ * </p>
+ *
+ * @param event the event to inject
+ * @param sync whether to inject the event synchronously
+ * @return {@code true} if event injection succeeded
*/
public boolean injectInputEvent(InputEvent event, boolean sync) {
return injectInputEvent(event, sync, true /* waitForAnimations */);
@@ -972,15 +986,21 @@ public final class UiAutomation {
* <strong>Note:</strong> It is caller's responsibility to recycle the event.
* </p>
*
- * @param event The event to inject.
- * @param sync Whether to inject the event synchronously.
- * @param waitForAnimations Whether to wait for all window container animations and surface
- * operations to complete.
- * @return Whether event injection succeeded.
+ * @param event the event to inject
+ * @param sync whether to inject the event synchronously.
+ * @param waitForAnimations whether to wait for all window container animations and surface
+ * operations to complete
+ * @return {@code true} if event injection succeeded
*
+ * @deprecated for CTS tests prefer inject input events using uinput
+ * (com.android.cts.input.UinputDevice) or hid devices (com.android.cts.input.HidDevice).
+ * Alternatively, InjectInputInProcess (com.android.cts.input.InjectInputProcess) can be used
+ * for in-process injection.
* @hide
*/
@TestApi
+ @Deprecated // Deprecated for CTS tests
+ @FlaggedApi(FLAG_DEPRECATE_UIAUTOMATION_INPUT_INJECTION)
public boolean injectInputEvent(@NonNull InputEvent event, boolean sync,
boolean waitForAnimations) {
try {
@@ -1003,9 +1023,15 @@ public final class UiAutomation {
* Events injected to the input subsystem using the standard {@link #injectInputEvent} method
* skip the accessibility input filter to avoid feedback loops.
*
+ * @deprecated for CTS tests prefer inject input events using uinput
+ * (com.android.cts.input.UinputDevice) or hid devices (com.android.cts.input.HidDevice).
+ * Alternatively, InjectInputInProcess (com.android.cts.input.InjectInputProcess) can be used
+ * for in-process injection.
* @hide
*/
@TestApi
+ @Deprecated
+ @FlaggedApi(FLAG_DEPRECATE_UIAUTOMATION_INPUT_INJECTION)
public void injectInputEventToInputFilter(@NonNull InputEvent event) {
try {
mUiAutomationConnection.injectInputEventToInputFilter(event);
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index a4a6a55fc9ab..733a348aa825 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -62,13 +62,6 @@ flag {
}
flag {
- name: "modes_ui_test"
- namespace: "systemui"
- description: "Guards new CTS tests for Modes; dependent on flags modes_api and modes_ui"
- bug: "360862012"
-}
-
-flag {
name: "modes_hsum"
namespace: "systemui"
description: "Fixes for modes (and DND/Zen in general) with HSUM or secondary users"
diff --git a/core/java/android/app/supervision/ISupervisionManager.aidl b/core/java/android/app/supervision/ISupervisionManager.aidl
index 4598421eb3bc..e583302e4d3b 100644
--- a/core/java/android/app/supervision/ISupervisionManager.aidl
+++ b/core/java/android/app/supervision/ISupervisionManager.aidl
@@ -22,4 +22,6 @@ package android.app.supervision;
*/
interface ISupervisionManager {
boolean isSupervisionEnabledForUser(int userId);
+ void setSupervisionEnabledForUser(int userId, boolean enabled);
+ String getActiveSupervisionAppPackage(int userId);
}
diff --git a/core/java/android/app/supervision/SupervisionManager.java b/core/java/android/app/supervision/SupervisionManager.java
index 92241f3634e8..a4efd77fce75 100644
--- a/core/java/android/app/supervision/SupervisionManager.java
+++ b/core/java/android/app/supervision/SupervisionManager.java
@@ -16,6 +16,7 @@
package android.app.supervision;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.annotation.UserHandleAware;
@@ -98,4 +99,49 @@ public class SupervisionManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Sets whether the device is supervised for the current user.
+ *
+ * @hide
+ */
+ @UserHandleAware
+ public void setSupervisionEnabled(boolean enabled) {
+ setSupervisionEnabledForUser(mContext.getUserId(), enabled);
+ }
+
+ /**
+ * Sets whether the device is supervised for a given user.
+ *
+ * <p>The caller must be from the same user as the target or hold the {@link
+ * android.Manifest.permission#INTERACT_ACROSS_USERS} permission.
+ *
+ * @hide
+ */
+ @RequiresPermission(
+ value = android.Manifest.permission.INTERACT_ACROSS_USERS,
+ conditional = true)
+ public void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled) {
+ try {
+ mService.setSupervisionEnabledForUser(userId, enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the package name of the app that is acting as the active supervision app or null if
+ * supervision is disabled.
+ *
+ * @hide
+ */
+ @UserHandleAware
+ @Nullable
+ public String getActiveSupervisionAppPackage() {
+ try {
+ return mService.getActiveSupervisionAppPackage(mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index 6da2a073ec19..1cf42820f356 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -18,13 +18,6 @@ flag {
}
flag {
- namespace: "virtual_devices"
- name: "media_projection_keyguard_restrictions"
- description: "Auto-stop MP when the device locks"
- bug: "348335290"
-}
-
-flag {
namespace: "virtual_devices"
name: "virtual_display_insets"
description: "APIs for specifying virtual display insets (via cutout)"
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8d54673df74c..8378695fd7a7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4270,6 +4270,7 @@ public abstract class Context {
//@hide: STATUS_BAR_SERVICE,
THREAD_NETWORK_SERVICE,
CONNECTIVITY_SERVICE,
+ TETHERING_SERVICE,
PAC_PROXY_SERVICE,
VCN_MANAGEMENT_SERVICE,
//@hide: IP_MEMORY_STORE_SERVICE,
@@ -4964,10 +4965,10 @@ public abstract class Context {
/**
* Use with {@link #getSystemService(String)} to retrieve a {@link android.net.TetheringManager}
* for managing tethering functions.
- * @hide
+ *
* @see android.net.TetheringManager
*/
- @SystemApi
+ @SuppressLint("UnflaggedApi")
public static final String TETHERING_SERVICE = "tethering";
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 219b20428d7a..b1ea6e9b68eb 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2628,6 +2628,15 @@ public class PackageParser {
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ targetCode)) {
+ Slog.w(TAG, "Package requires development platform " + targetCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return Build.VERSION.SDK_INT;
+ }
+
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + targetCode
@@ -2699,6 +2708,15 @@ public class PackageParser {
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ minCode)) {
+ Slog.w(TAG, "Package requires min development platform " + minCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return Build.VERSION.SDK_INT;
+ }
+
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + minCode
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index e30f871b68eb..d2d3a6840acc 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -316,6 +316,15 @@ public class FrameworkParsingPackageUtils {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ minCode)) {
+ Slog.w(TAG, "Parsed package requires min development platform " + minCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return input.success(Build.VERSION.SDK_INT);
+ }
+
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
@@ -398,19 +407,27 @@ public class FrameworkParsingPackageUtils {
return input.success(targetVers);
}
+ // If it's a pre-release SDK and the codename matches this platform, it
+ // definitely targets this SDK.
+ if (matchTargetCode(platformSdkCodenames, targetCode)) {
+ return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ }
+
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ targetCode)) {
+ Slog.w(TAG, "Parsed package requires development platform " + targetCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return input.success(Build.VERSION.SDK_INT);
+ }
+
try {
if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
} catch (IllegalArgumentException e) {
- // isAtMost() throws it when encountering an older SDK codename
- return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
- }
-
- // If it's a pre-release SDK and the codename matches this platform, it
- // definitely targets this SDK.
- if (matchTargetCode(platformSdkCodenames, targetCode)) {
- return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
}
// Otherwise, we're looking at an incompatible pre-release SDK.
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index f649e476ffca..7dc6afba3f1c 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -178,6 +178,15 @@ public interface BiometricConstants {
@FlaggedApi(Flags.FLAG_IDENTITY_CHECK_API)
int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = 21;
+
+ /**
+ * The user pressed the more options button on prompt content. This is a placeholder that is
+ * currently only used by the support library.
+ *
+ * @hide
+ */
+ int BIOMETRIC_ERROR_CONTENT_VIEW_MORE_OPTIONS_BUTTON = 22;
+
/**
* This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
* because the authentication attempt was unsuccessful.
@@ -209,6 +218,7 @@ public interface BiometricConstants {
BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
BIOMETRIC_ERROR_IDENTITY_CHECK_NOT_ACTIVE,
BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS,
+ BIOMETRIC_ERROR_CONTENT_VIEW_MORE_OPTIONS_BUTTON,
BIOMETRIC_PAUSED_REJECTED})
@Retention(RetentionPolicy.SOURCE)
@interface Errors {}
@@ -324,6 +334,5 @@ public interface BiometricConstants {
* Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when there has
* been no successful authentication for the given authenticator since boot.
*/
- @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
long BIOMETRIC_NO_AUTHENTICATION = -1;
}
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index c690c67ed79f..cefe20c15ced 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -116,7 +116,6 @@ public class BiometricManager {
* Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when no matching
* successful authentication has been performed since boot.
*/
- @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
public static final long BIOMETRIC_NO_AUTHENTICATION =
BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
@@ -777,7 +776,6 @@ public class BiometricManager {
*/
@RequiresPermission(USE_BIOMETRIC)
@ElapsedRealtimeLong
- @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
public long getLastAuthenticationTime(
@BiometricManager.Authenticators.Types int authenticators) {
if (authenticators == 0
diff --git a/core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java b/core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java
index de93234445ca..d3fb93588762 100644
--- a/core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java
+++ b/core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java
@@ -19,6 +19,7 @@ package android.hardware.biometrics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
+import android.app.supervision.SupervisionManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build;
@@ -55,27 +56,44 @@ public class ParentalControlsUtilsInternal {
return null;
}
- public static boolean parentConsentRequired(@NonNull Context context,
- @NonNull DevicePolicyManager dpm, @BiometricAuthenticator.Modality int modality,
+ /** @return true if parental consent is required in order for biometric sensors to be used. */
+ public static boolean parentConsentRequired(
+ @NonNull Context context,
+ @NonNull DevicePolicyManager dpm,
+ @Nullable SupervisionManager sm,
+ @BiometricAuthenticator.Modality int modality,
@NonNull UserHandle userHandle) {
if (getTestComponentName(context, userHandle.getIdentifier()) != null) {
return true;
}
- return parentConsentRequired(dpm, modality, userHandle);
+ return parentConsentRequired(dpm, sm, modality, userHandle);
}
/**
* @return true if parental consent is required in order for biometric sensors to be used.
*/
- public static boolean parentConsentRequired(@NonNull DevicePolicyManager dpm,
- @BiometricAuthenticator.Modality int modality, @NonNull UserHandle userHandle) {
- final ComponentName cn = getSupervisionComponentName(dpm, userHandle);
- if (cn == null) {
- return false;
+ public static boolean parentConsentRequired(
+ @NonNull DevicePolicyManager dpm,
+ @Nullable SupervisionManager sm,
+ @BiometricAuthenticator.Modality int modality,
+ @NonNull UserHandle userHandle) {
+ final int keyguardDisabledFeatures;
+
+ if (android.app.supervision.flags.Flags.deprecateDpmSupervisionApis()) {
+ if (sm != null && !sm.isSupervisionEnabledForUser(userHandle.getIdentifier())) {
+ return false;
+ }
+ // Check for keyguard features disabled by any admin.
+ keyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(/* admin= */ null);
+ } else {
+ final ComponentName cn = getSupervisionComponentName(dpm, userHandle);
+ if (cn == null) {
+ return false;
+ }
+ keyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(cn);
}
- final int keyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(cn);
final boolean dpmFpDisabled = containsFlag(keyguardDisabledFeatures,
DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
final boolean dpmFaceDisabled = containsFlag(keyguardDisabledFeatures,
@@ -97,7 +115,9 @@ public class ParentalControlsUtilsInternal {
return consentRequired;
}
+ /** @deprecated Use {@link SupervisionManager} to check for supervision. */
@Nullable
+ @Deprecated
public static ComponentName getSupervisionComponentName(@NonNull DevicePolicyManager dpm,
@NonNull UserHandle userHandle) {
return dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(userHandle);
diff --git a/core/java/android/hardware/biometrics/flags.aconfig b/core/java/android/hardware/biometrics/flags.aconfig
index 73b6417a6ba4..4815f3e4f524 100644
--- a/core/java/android/hardware/biometrics/flags.aconfig
+++ b/core/java/android/hardware/biometrics/flags.aconfig
@@ -2,14 +2,6 @@ package: "android.hardware.biometrics"
container: "system"
flag {
- name: "last_authentication_time"
- is_exported: true
- namespace: "wallet_integration"
- description: "Feature flag for adding getLastAuthenticationTime API to BiometricManager"
- bug: "301979982"
-}
-
-flag {
name: "add_key_agreement_crypto_object"
is_exported: true
namespace: "biometrics"
diff --git a/core/java/android/hardware/contexthub/HubEndpoint.java b/core/java/android/hardware/contexthub/HubEndpoint.java
index 14911de6d032..b7edef619a67 100644
--- a/core/java/android/hardware/contexthub/HubEndpoint.java
+++ b/core/java/android/hardware/contexthub/HubEndpoint.java
@@ -122,16 +122,11 @@ public class HubEndpoint {
HubEndpointInfo initiator,
@Nullable String serviceDescriptor)
throws RemoteException {
- boolean sessionExists;
- synchronized (mLock) {
- sessionExists = mActiveSessions.contains(sessionId);
- // TODO(b/378974199): Consider refactor these assertions
- if (sessionExists) {
- Log.w(
- TAG,
- "onSessionOpenComplete: session already exists, id="
- + sessionId);
- }
+ boolean sessionExists = getActiveSession(sessionId) != null;
+ if (sessionExists) {
+ Log.w(
+ TAG,
+ "onSessionOpenComplete: session already exists, id=" + sessionId);
}
if (!sessionExists && mLifecycleCallback != null) {
@@ -150,13 +145,7 @@ public class HubEndpoint {
@Override
public void onSessionOpenComplete(int sessionId) throws RemoteException {
- final HubEndpointSession activeSession;
-
- // Retrieve the active session
- synchronized (mLock) {
- activeSession = mActiveSessions.get(sessionId);
- }
- // TODO(b/378974199): Consider refactor these assertions
+ final HubEndpointSession activeSession = getActiveSession(sessionId);
if (activeSession == null) {
Log.w(
TAG,
@@ -179,13 +168,7 @@ public class HubEndpoint {
@Override
public void onSessionClosed(int sessionId, int reason) throws RemoteException {
- final HubEndpointSession activeSession;
-
- // Retrieve the active session
- synchronized (mLock) {
- activeSession = mActiveSessions.get(sessionId);
- }
- // TODO(b/378974199): Consider refactor these assertions
+ final HubEndpointSession activeSession = getActiveSession(sessionId);
if (activeSession == null) {
Log.w(TAG, "onSessionClosed: session not active, id=" + sessionId);
}
@@ -211,12 +194,7 @@ public class HubEndpoint {
@Override
public void onMessageReceived(int sessionId, HubMessage message)
throws RemoteException {
- final HubEndpointSession activeSession;
-
- // Retrieve the active session
- synchronized (mLock) {
- activeSession = mActiveSessions.get(sessionId);
- }
+ final HubEndpointSession activeSession = getActiveSession(sessionId);
if (activeSession == null) {
Log.w(TAG, "onMessageReceived: session not active, id=" + sessionId);
}
@@ -233,6 +211,12 @@ public class HubEndpoint {
}
}
+ private HubEndpointSession getActiveSession(int sessionId) {
+ synchronized (mLock) {
+ return mActiveSessions.get(sessionId);
+ }
+ }
+
private void sendMessageDeliveryStatus(
int sessionId, HubMessage message, byte errorCode) {
if (message.isResponseRequired()) {
diff --git a/core/java/android/hardware/display/DisplayTopology.java b/core/java/android/hardware/display/DisplayTopology.java
index b39bd8c10022..555ff4b271fd 100644
--- a/core/java/android/hardware/display/DisplayTopology.java
+++ b/core/java/android/hardware/display/DisplayTopology.java
@@ -33,6 +33,7 @@ import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.Display;
import androidx.annotation.NonNull;
@@ -61,6 +62,7 @@ import java.util.Queue;
public final class DisplayTopology implements Parcelable {
private static final String TAG = "DisplayTopology";
private static final float EPSILON = 0.0001f;
+ private static final float MAX_GAP = 5;
@android.annotation.NonNull
public static final Creator<DisplayTopology> CREATOR =
@@ -108,7 +110,7 @@ public final class DisplayTopology implements Parcelable {
public DisplayTopology() {}
- public DisplayTopology(TreeNode root, int primaryDisplayId) {
+ public DisplayTopology(@Nullable TreeNode root, int primaryDisplayId) {
mRoot = root;
if (mRoot != null) {
// Set mRoot's position and offset to predictable values, just so we don't leak state
@@ -181,6 +183,8 @@ public final class DisplayTopology implements Parcelable {
if (findDisplay(displayId, mRoot) == null) {
return false;
}
+
+ // Re-add the other displays to a new tree
Queue<TreeNode> queue = new ArrayDeque<>();
queue.add(mRoot);
mRoot = null;
@@ -191,6 +195,7 @@ public final class DisplayTopology implements Parcelable {
}
queue.addAll(node.mChildren);
}
+
if (mPrimaryDisplayId == displayId) {
if (mRoot != null) {
mPrimaryDisplayId = mRoot.mDisplayId;
@@ -218,6 +223,9 @@ public final class DisplayTopology implements Parcelable {
* IDs in this topology, no more, no less
*/
public void rearrange(Map<Integer, PointF> newPos) {
+ if (mRoot == null) {
+ return;
+ }
var availableParents = new ArrayList<TreeNode>();
availableParents.addLast(mRoot);
@@ -447,11 +455,11 @@ public final class DisplayTopology implements Parcelable {
// Check that the offset is within bounds
areTouching &= switch (targetDisplay.mPosition) {
case POSITION_LEFT, POSITION_RIGHT ->
- childBounds.bottom + EPSILON >= parentBounds.top
- && childBounds.top <= parentBounds.bottom + EPSILON;
+ childBounds.bottom + EPSILON > parentBounds.top
+ && childBounds.top < parentBounds.bottom + EPSILON;
case POSITION_TOP, POSITION_BOTTOM ->
- childBounds.right + EPSILON >= parentBounds.left
- && childBounds.left <= parentBounds.right + EPSILON;
+ childBounds.right + EPSILON > parentBounds.left
+ && childBounds.left < parentBounds.right + EPSILON;
default -> throw new IllegalStateException(
"Unexpected value: " + targetDisplay.mPosition);
};
@@ -566,7 +574,7 @@ public final class DisplayTopology implements Parcelable {
"DisplayTopology: attempting to add a display that already exists");
}
if (mRoot == null) {
- mRoot = new TreeNode(displayId, width, height, /* position= */ 0, /* offset= */ 0);
+ mRoot = new TreeNode(displayId, width, height, POSITION_LEFT, /* offset= */ 0);
mPrimaryDisplayId = displayId;
if (shouldLog) {
Slog.i(TAG, "First display added: " + mRoot);
@@ -681,13 +689,112 @@ public final class DisplayTopology implements Parcelable {
}
}
- /** Returns the graph representation of the topology */
- public DisplayTopologyGraph getGraph() {
- // TODO(b/364907904): implement
- return new DisplayTopologyGraph(mPrimaryDisplayId,
- new DisplayTopologyGraph.DisplayNode[] { new DisplayTopologyGraph.DisplayNode(
- mRoot == null ? Display.DEFAULT_DISPLAY : mRoot.mDisplayId,
- new DisplayTopologyGraph.AdjacentDisplay[0])});
+ /**
+ * Check if two displays are touching.
+ * If the gap between two edges is <= {@link MAX_GAP}, they are still considered adjacent.
+ * The position indicates where the second display is touching the first one and the offset
+ * indicates where along the first display the second display is located.
+ * @param bounds1 The bounds of the first display
+ * @param bounds2 The bounds of the second display
+ * @return Empty list if the displays are not adjacent;
+ * List of one Pair(position, offset) if the displays are adjacent but not by a corner;
+ * List of two Pair(position, offset) if the displays are adjacent by a corner.
+ */
+ private List<Pair<Integer, Float>> findDisplayPlacements(RectF bounds1, RectF bounds2) {
+ List<Pair<Integer, Float>> placements = new ArrayList<>();
+ if (bounds1.top <= bounds2.bottom + MAX_GAP && bounds2.top <= bounds1.bottom + MAX_GAP) {
+ if (MathUtils.abs(bounds1.left - bounds2.right) <= MAX_GAP) {
+ placements.add(new Pair<>(POSITION_LEFT, bounds2.top - bounds1.top));
+ }
+ if (MathUtils.abs(bounds1.right - bounds2.left) <= MAX_GAP) {
+ placements.add(new Pair<>(POSITION_RIGHT, bounds2.top - bounds1.top));
+ }
+ }
+ if (bounds1.left <= bounds2.right + MAX_GAP && bounds2.left <= bounds1.right + MAX_GAP) {
+ if (MathUtils.abs(bounds1.top - bounds2.bottom) < MAX_GAP) {
+ placements.add(new Pair<>(POSITION_TOP, bounds2.left - bounds1.left));
+ }
+ if (MathUtils.abs(bounds1.bottom - bounds2.top) < MAX_GAP) {
+ placements.add(new Pair<>(POSITION_BOTTOM, bounds2.left - bounds1.left));
+ }
+ }
+ return placements;
+ }
+
+ /**
+ * @param densityPerDisplay The logical display densities, indexed by logical display ID
+ * @return The graph representation of the topology. If there is a corner adjacency, the same
+ * display will appear twice in the list of adjacent displays with both possible placements.
+ */
+ @Nullable
+ public DisplayTopologyGraph getGraph(SparseIntArray densityPerDisplay) {
+ // Sort the displays by position
+ SparseArray<RectF> bounds = getAbsoluteBounds();
+ Comparator<Integer> comparator = (displayId1, displayId2) -> {
+ RectF bounds1 = bounds.get(displayId1);
+ RectF bounds2 = bounds.get(displayId2);
+
+ int compareX = Float.compare(bounds1.left, bounds2.left);
+ if (compareX != 0) {
+ return compareX;
+ }
+ return Float.compare(bounds1.top, bounds2.top);
+ };
+ List<Integer> displayIds = new ArrayList<>(bounds.size());
+ for (int i = 0; i < bounds.size(); i++) {
+ displayIds.add(bounds.keyAt(i));
+ }
+ displayIds.sort(comparator);
+
+ SparseArray<List<DisplayTopologyGraph.AdjacentDisplay>> adjacentDisplaysPerId =
+ new SparseArray<>();
+ for (int id : displayIds) {
+ if (densityPerDisplay.get(id) == 0) {
+ Slog.w(TAG, "Cannot construct graph, no density for display " + id);
+ return null;
+ }
+ adjacentDisplaysPerId.append(id, new ArrayList<>(Math.min(10, displayIds.size())));
+ }
+
+ // Find touching displays
+ for (int i = 0; i < displayIds.size(); i++) {
+ int displayId1 = displayIds.get(i);
+ RectF bounds1 = bounds.get(displayId1);
+ List<DisplayTopologyGraph.AdjacentDisplay> adjacentDisplays1 =
+ adjacentDisplaysPerId.get(displayId1);
+
+ for (int j = i + 1; j < displayIds.size(); j++) {
+ int displayId2 = displayIds.get(j);
+ RectF bounds2 = bounds.get(displayId2);
+ List<DisplayTopologyGraph.AdjacentDisplay> adjacentDisplays2 =
+ adjacentDisplaysPerId.get(displayId2);
+
+ List<Pair<Integer, Float>> placements1 = findDisplayPlacements(bounds1, bounds2);
+ List<Pair<Integer, Float>> placements2 = findDisplayPlacements(bounds2, bounds1);
+ for (Pair<Integer, Float> placement : placements1) {
+ adjacentDisplays1.add(new DisplayTopologyGraph.AdjacentDisplay(displayId2,
+ /* position= */ placement.first, /* offsetDp= */ placement.second));
+ }
+ for (Pair<Integer, Float> placement : placements2) {
+ adjacentDisplays2.add(new DisplayTopologyGraph.AdjacentDisplay(displayId1,
+ /* position= */ placement.first, /* offsetDp= */ placement.second));
+ }
+ if (bounds2.left >= bounds1.right + EPSILON) {
+ // This and the subsequent displays are already too far away
+ break;
+ }
+ }
+ }
+
+ DisplayTopologyGraph.DisplayNode[] nodes =
+ new DisplayTopologyGraph.DisplayNode[adjacentDisplaysPerId.size()];
+ for (int i = 0; i < nodes.length; i++) {
+ int displayId = adjacentDisplaysPerId.keyAt(i);
+ nodes[i] = new DisplayTopologyGraph.DisplayNode(displayId,
+ densityPerDisplay.get(displayId), adjacentDisplaysPerId.valueAt(i).toArray(
+ new DisplayTopologyGraph.AdjacentDisplay[0]));
+ }
+ return new DisplayTopologyGraph(mPrimaryDisplayId, nodes);
}
/**
diff --git a/core/java/android/hardware/display/DisplayTopologyGraph.java b/core/java/android/hardware/display/DisplayTopologyGraph.java
index 938e6d108f5d..99528cc3a3d2 100644
--- a/core/java/android/hardware/display/DisplayTopologyGraph.java
+++ b/core/java/android/hardware/display/DisplayTopologyGraph.java
@@ -16,6 +16,8 @@
package android.hardware.display;
+import static android.hardware.display.DisplayTopology.TreeNode.positionToString;
+
/**
* Graph of the displays in {@link android.hardware.display.DisplayTopology} tree.
*
@@ -27,6 +29,7 @@ public record DisplayTopologyGraph(int primaryDisplayId, DisplayNode[] displayNo
*/
public record DisplayNode(
int displayId,
+ int density,
AdjacentDisplay[] adjacentDisplays) {}
/**
@@ -38,6 +41,18 @@ public record DisplayTopologyGraph(int primaryDisplayId, DisplayNode[] displayNo
// Side of the other display which touches this adjacent display.
@DisplayTopology.TreeNode.Position
int position,
- // How many px this display is shifted along the touchingSide, can be negative.
- float offsetPx) {}
+ // The distance from the top edge of the other display to the top edge of this display
+ // (in case of POSITION_LEFT or POSITION_RIGHT) or from the left edge of the parent
+ // display to the left edge of this display (in case of POSITION_TOP or
+ // POSITION_BOTTOM). The unit used is density-independent pixels (dp).
+ float offsetDp) {
+ @Override
+ public String toString() {
+ return "AdjacentDisplay{"
+ + "displayId=" + displayId
+ + ", position=" + positionToString(position)
+ + ", offsetDp=" + offsetDp
+ + '}';
+ }
+ }
}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 2bb28a1b6b0b..7fc7e4d81afa 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -106,6 +106,12 @@ interface IInputManager {
@EnforcePermission("SET_KEYBOARD_LAYOUT")
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
+ void setKeyboardLayoutOverrideForInputDevice(in InputDeviceIdentifier identifier,
+ String keyboardLayoutDescriptor);
+
+ @EnforcePermission("SET_KEYBOARD_LAYOUT")
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ + "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
void setKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier, int userId,
in InputMethodInfo imeInfo, in InputMethodSubtype imeSubtype,
String keyboardLayoutDescriptor);
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index 3ef90e4b8a5f..e79416162fc2 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -57,6 +57,8 @@ import android.view.InputMonitor;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.PointerIcon;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -1256,6 +1258,43 @@ public final class InputManagerGlobal {
}
/**
+ * Sets the keyboard layout override for the specified input device. This will set the
+ * keyboard layout as the default for the input device irrespective of the underlying IME
+ * configuration.
+ *
+ * <p>
+ * Prefer using {@link InputManager#setKeyboardLayoutForInputDevice(InputDeviceIdentifier, int,
+ * InputMethodInfo, InputMethodSubtype, String)} for normal use cases.
+ * </p><p>
+ * This method is to be used only for special cases where we knowingly want to set a
+ * particular keyboard layout for a keyboard, ignoring the IME configuration. e.g. Setting a
+ * default layout for an Android Emulator where we know the preferred H/W keyboard layout.
+ * </p><p>
+ * NOTE: This may affect the typing experience if the layout isn't compatible with the IME
+ * configuration.
+ * </p><p>
+ * NOTE: User can still change the keyboard layout configuration from the settings page.
+ * </p>
+ *
+ * @param identifier The identifier for the input device.
+ * @param keyboardLayoutDescriptor The keyboard layout descriptor to use.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
+ public void setKeyboardLayoutOverrideForInputDevice(@NonNull InputDeviceIdentifier identifier,
+ @NonNull String keyboardLayoutDescriptor) {
+ Objects.requireNonNull(identifier, "identifier should not be null");
+ Objects.requireNonNull(keyboardLayoutDescriptor,
+ "keyboardLayoutDescriptor should not be null");
+ try {
+ mIm.setKeyboardLayoutOverrideForInputDevice(identifier, keyboardLayoutDescriptor);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* TODO(b/330517633): Cleanup the unsupported API
*/
@NonNull
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index 8ca139fdf9b9..f420b5d7b886 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -16,9 +16,9 @@
package android.inputmethodservice;
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_VISIBLE;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
+import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
@@ -242,11 +242,11 @@ final class NavigationBarController {
NavigationBarView.class::isInstance);
if (navigationBarView != null) {
// TODO(b/213337792): Support InputMethodService#setBackDisposition().
- // TODO(b/213337792): Set NAVIGATION_HINT_IME_VISIBLE only when necessary.
- final int hints = NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_VISIBLE
+ // TODO(b/213337792): Set NAVBAR_IME_VISIBLE only when necessary.
+ final int flags = NAVBAR_BACK_DISMISS_IME | NAVBAR_IME_VISIBLE
| (mShouldShowImeSwitcherWhenImeIsShown
- ? NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE : 0);
- navigationBarView.setNavigationIconHints(hints);
+ ? NAVBAR_IME_SWITCHER_BUTTON_VISIBLE : 0);
+ navigationBarView.setNavbarFlags(flags);
navigationBarView.prepareNavButtons(this);
}
} else {
@@ -515,11 +515,11 @@ final class NavigationBarController {
NavigationBarView.class::isInstance);
if (navigationBarView != null) {
// TODO(b/213337792): Support InputMethodService#setBackDisposition().
- // TODO(b/213337792): Set NAVIGATION_HINT_IME_VISIBLE only when necessary.
- final int hints = NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_VISIBLE
+ // TODO(b/213337792): Set NAVBAR_IME_VISIBLE only when necessary.
+ final int flags = NAVBAR_BACK_DISMISS_IME | NAVBAR_IME_VISIBLE
| (mShouldShowImeSwitcherWhenImeIsShown
- ? NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE : 0);
- navigationBarView.setNavigationIconHints(hints);
+ ? NAVBAR_IME_SWITCHER_BUTTON_VISIBLE : 0);
+ navigationBarView.setNavbarFlags(flags);
}
} else {
uninstallNavigationBarFrameIfNecessary();
diff --git a/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java b/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java
index 5c0977115e36..960a5b33434a 100644
--- a/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java
+++ b/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java
@@ -16,8 +16,8 @@
package android.inputmethodservice.navigationbar;
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
+import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
import static android.inputmethodservice.navigationbar.NavigationBarConstants.DARK_MODE_ICON_COLOR_SINGLE_TONE;
import static android.inputmethodservice.navigationbar.NavigationBarConstants.LIGHT_MODE_ICON_COLOR_SINGLE_TONE;
import static android.inputmethodservice.navigationbar.NavigationBarConstants.NAVBAR_BACK_BUTTON_IME_OFFSET;
@@ -30,7 +30,7 @@ import android.annotation.DrawableRes;
import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.app.StatusBarManager;
-import android.app.StatusBarManager.NavigationHint;
+import android.app.StatusBarManager.NavbarFlags;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
@@ -66,8 +66,8 @@ public final class NavigationBarView extends FrameLayout {
private int mCurrentRotation = -1;
int mDisabledFlags = 0;
- @NavigationHint
- private int mNavigationIconHints = 0;
+ @NavbarFlags
+ private int mNavbarFlags;
private final int mNavBarMode = NAV_BAR_MODE_GESTURAL;
private KeyButtonDrawable mBackIcon;
@@ -245,9 +245,9 @@ public final class NavigationBarView extends FrameLayout {
}
private void orientBackButton(KeyButtonDrawable drawable) {
- final boolean useAltBack = (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0;
+ final boolean isBackDismissIme = (mNavbarFlags & NAVBAR_BACK_DISMISS_IME) != 0;
final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
+ float degrees = isBackDismissIme ? (isRtl ? 90 : -90) : 0;
if (drawable.getRotation() == degrees) {
return;
}
@@ -259,7 +259,7 @@ public final class NavigationBarView extends FrameLayout {
// Animate the back button's rotation to the new degrees and only in portrait move up the
// back button to line up with the other buttons
- float targetY = useAltBack
+ float targetY = isBackDismissIme
? -dpToPx(NAVBAR_BACK_BUTTON_IME_OFFSET, getResources())
: 0;
ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable,
@@ -283,26 +283,26 @@ public final class NavigationBarView extends FrameLayout {
}
/**
- * Updates the navigation icons based on {@code hints}.
+ * Sets the navigation bar state flags.
*
- * @param hints bit flags defined in {@link StatusBarManager}.
+ * @param flags the navigation bar state flags.
*/
- public void setNavigationIconHints(@NavigationHint int hints) {
- if (hints == mNavigationIconHints) {
+ public void setNavbarFlags(@NavbarFlags int flags) {
+ if (flags == mNavbarFlags) {
return;
}
- final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
- final boolean oldBackAlt =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
- if (newBackAlt != oldBackAlt) {
- //onBackAltChanged(newBackAlt);
+ final boolean backDismissIme = (flags & StatusBarManager.NAVBAR_BACK_DISMISS_IME) != 0;
+ final boolean oldBackDismissIme =
+ (mNavbarFlags & StatusBarManager.NAVBAR_BACK_DISMISS_IME) != 0;
+ if (backDismissIme != oldBackDismissIme) {
+ //onBackDismissImeChanged(backDismissIme);
}
if (DEBUG) {
- android.widget.Toast.makeText(getContext(), "Navigation icon hints = " + hints, 500)
+ android.widget.Toast.makeText(getContext(), "Navbar flags = " + flags, 500)
.show();
}
- mNavigationIconHints = hints;
+ mNavbarFlags = flags;
updateNavButtonIcons();
}
@@ -319,7 +319,7 @@ public final class NavigationBarView extends FrameLayout {
// Update IME switcher button visibility, a11y and rotate button always overrides
// the appearance.
final boolean isImeSwitcherButtonVisible =
- (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0;
+ (mNavbarFlags & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0;
getImeSwitchButton()
.setVisibility(isImeSwitcherButtonVisible ? View.VISIBLE : View.INVISIBLE);
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index f913fcfd56d4..86b8fad16275 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -161,6 +161,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
private final List<UserBatteryConsumer> mUserBatteryConsumers;
private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
private final BatteryStatsHistory mBatteryStatsHistory;
+ private final long mPreferredHistoryDurationMs;
private final BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
private CursorWindow mBatteryConsumersCursorWindow;
@@ -174,6 +175,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
mDischargeDurationMs = builder.mDischargeDurationMs;
mBatteryStatsHistory = builder.mBatteryStatsHistory;
+ mPreferredHistoryDurationMs = builder.mPreferredHistoryDurationMs;
mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
@@ -402,8 +404,10 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
if (source.readBoolean()) {
mBatteryStatsHistory = BatteryStatsHistory.createFromBatteryUsageStatsParcel(source);
+ mPreferredHistoryDurationMs = source.readLong();
} else {
mBatteryStatsHistory = null;
+ mPreferredHistoryDurationMs = 0;
}
}
@@ -428,7 +432,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
if (mBatteryStatsHistory != null) {
dest.writeBoolean(true);
- mBatteryStatsHistory.writeToBatteryUsageStatsParcel(dest);
+ mBatteryStatsHistory.writeToBatteryUsageStatsParcel(dest, mPreferredHistoryDurationMs);
} else {
dest.writeBoolean(false);
}
@@ -919,6 +923,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
private final SparseArray<UserBatteryConsumer.Builder> mUserBatteryConsumerBuilders =
new SparseArray<>();
private BatteryStatsHistory mBatteryStatsHistory;
+ private long mPreferredHistoryDurationMs;
public Builder(@NonNull String[] customPowerComponentNames) {
this(customPowerComponentNames, false, false, false, 0);
@@ -1092,8 +1097,10 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
* Sets the parceled recent history.
*/
@NonNull
- public Builder setBatteryHistory(BatteryStatsHistory batteryStatsHistory) {
+ public Builder setBatteryHistory(BatteryStatsHistory batteryStatsHistory,
+ long preferredHistoryDurationMs) {
mBatteryStatsHistory = batteryStatsHistory;
+ mPreferredHistoryDurationMs = preferredHistoryDurationMs;
return this;
}
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index 6e67578fadc8..5aed39bd8fa6 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -25,6 +25,7 @@ import com.android.internal.os.MonotonicClock;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
/**
* Query parameters for the {@link BatteryStatsManager#getBatteryUsageStats()} call.
@@ -77,6 +78,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
public static final int FLAG_BATTERY_USAGE_STATS_ACCUMULATED = 0x0080;
private static final long DEFAULT_MAX_STATS_AGE_MS = 5 * 60 * 1000;
+ private static final long DEFAULT_PREFERRED_HISTORY_DURATION_MS = TimeUnit.HOURS.toMillis(2);
private final int mFlags;
@NonNull
@@ -89,6 +91,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
private long mMonotonicEndTime;
private final double mMinConsumedPowerThreshold;
private final @BatteryConsumer.PowerComponentId int[] mPowerComponents;
+ private final long mPreferredHistoryDurationMs;
private BatteryUsageStatsQuery(@NonNull Builder builder) {
mFlags = builder.mFlags;
@@ -101,6 +104,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mMonotonicStartTime = builder.mMonotonicStartTime;
mMonotonicEndTime = builder.mMonotonicEndTime;
mPowerComponents = builder.mPowerComponents;
+ mPreferredHistoryDurationMs = builder.mPreferredHistoryDurationMs;
}
@BatteryUsageStatsFlags
@@ -197,6 +201,13 @@ public final class BatteryUsageStatsQuery implements Parcelable {
return mAggregatedToTimestamp;
}
+ /**
+ * Returns the preferred duration of battery history (tail) to be included in the query result.
+ */
+ public long getPreferredHistoryDurationMs() {
+ return mPreferredHistoryDurationMs;
+ }
+
@Override
public String toString() {
return "BatteryUsageStatsQuery{"
@@ -209,6 +220,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
+ ", mMonotonicEndTime=" + mMonotonicEndTime
+ ", mMinConsumedPowerThreshold=" + mMinConsumedPowerThreshold
+ ", mPowerComponents=" + Arrays.toString(mPowerComponents)
+ + ", mMaxHistoryDurationMs=" + mPreferredHistoryDurationMs
+ '}';
}
@@ -223,6 +235,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mAggregatedFromTimestamp = in.readLong();
mAggregatedToTimestamp = in.readLong();
mPowerComponents = in.createIntArray();
+ mPreferredHistoryDurationMs = in.readLong();
}
@Override
@@ -237,6 +250,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
dest.writeLong(mAggregatedFromTimestamp);
dest.writeLong(mAggregatedToTimestamp);
dest.writeIntArray(mPowerComponents);
+ dest.writeLong(mPreferredHistoryDurationMs);
}
@Override
@@ -271,6 +285,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
private long mAggregateToTimestamp;
private double mMinConsumedPowerThreshold = 0;
private @BatteryConsumer.PowerComponentId int[] mPowerComponents;
+ private long mPreferredHistoryDurationMs = DEFAULT_PREFERRED_HISTORY_DURATION_MS;
/**
* Builds a read-only BatteryUsageStatsQuery object.
@@ -311,6 +326,16 @@ public final class BatteryUsageStatsQuery implements Parcelable {
}
/**
+ * Set the preferred amount of battery history to be included in the result, provided
+ * that `includeBatteryHistory` is also called. The actual amount of history included in
+ * the result may vary for performance reasons and may exceed the specified preference.
+ */
+ public Builder setPreferredHistoryDurationMs(long preferredHistoryDurationMs) {
+ mPreferredHistoryDurationMs = preferredHistoryDurationMs;
+ return this;
+ }
+
+ /**
* Requests that per-process state data be included in the BatteryUsageStats, if
* available. Check {@link BatteryUsageStats#isProcessStateDataIncluded()} on the result
* to see if the data is available.
diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
index 1e663342522b..877f130a8b5a 100644
--- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
@@ -601,7 +601,7 @@ public final class MessageQueue {
/* This is only read/written from the Looper thread. For use with Concurrent MQ */
private int mNextPollTimeoutMillis;
private boolean mMessageDirectlyQueued;
- private Message nextMessage(boolean peek) {
+ private Message nextMessage(boolean peek, boolean returnEarliest) {
int i = 0;
while (true) {
@@ -678,7 +678,7 @@ public final class MessageQueue {
* If we have a barrier we should return the async node (if it exists and is ready)
*/
if (msgNode != null && msgNode.isBarrier()) {
- if (asyncMsgNode != null && now >= asyncMsgNode.getWhen()) {
+ if (asyncMsgNode != null && (returnEarliest || now >= asyncMsgNode.getWhen())) {
found = asyncMsgNode;
} else {
next = asyncMsgNode;
@@ -692,7 +692,7 @@ public final class MessageQueue {
earliest = pickEarliestNode(msgNode, asyncMsgNode);
if (earliest != null) {
- if (now >= earliest.getWhen()) {
+ if (returnEarliest || now >= earliest.getWhen()) {
found = earliest;
} else {
next = earliest;
@@ -797,7 +797,7 @@ public final class MessageQueue {
mMessageDirectlyQueued = false;
nativePollOnce(ptr, mNextPollTimeoutMillis);
- Message msg = nextMessage(false);
+ Message msg = nextMessage(false, false);
if (msg != null) {
msg.markInUse();
return msg;
@@ -1374,27 +1374,27 @@ public final class MessageQueue {
if (now >= msg.when) {
// Got a message.
mBlocked = false;
- if (prevMsg != null) {
- prevMsg.next = msg.next;
- if (prevMsg.next == null) {
- mLast = prevMsg;
- }
- } else {
- mMessages = msg.next;
- if (msg.next == null) {
- mLast = null;
- }
- }
- msg.next = null;
- msg.markInUse();
- if (msg.isAsynchronous()) {
- mAsyncMessageCount--;
+ }
+ if (prevMsg != null) {
+ prevMsg.next = msg.next;
+ if (prevMsg.next == null) {
+ mLast = prevMsg;
}
- if (TRACE) {
- Trace.setCounter("MQ.Delivered", mMessagesDelivered.incrementAndGet());
+ } else {
+ mMessages = msg.next;
+ if (msg.next == null) {
+ mLast = null;
}
- return msg;
}
+ msg.next = null;
+ msg.markInUse();
+ if (msg.isAsynchronous()) {
+ mAsyncMessageCount--;
+ }
+ if (TRACE) {
+ Trace.setCounter("MQ.Delivered", mMessagesDelivered.incrementAndGet());
+ }
+ return msg;
}
}
return null;
@@ -1411,7 +1411,7 @@ public final class MessageQueue {
throwIfNotTest();
Message ret;
if (mUseConcurrent) {
- ret = nextMessage(true);
+ ret = nextMessage(true, true);
} else {
ret = legacyPeekOrPoll(true);
}
@@ -1429,7 +1429,7 @@ public final class MessageQueue {
Message pollForTest() {
throwIfNotTest();
if (mUseConcurrent) {
- return nextMessage(false);
+ return nextMessage(false, true);
} else {
return legacyPeekOrPoll(false);
}
@@ -1446,7 +1446,7 @@ public final class MessageQueue {
throwIfNotTest();
if (mUseConcurrent) {
// Call nextMessage to get the stack drained into our priority queues
- nextMessage(true);
+ nextMessage(true, false);
Iterator<MessageNode> queueIter = mPriorityQueue.iterator();
MessageNode queueNode = iterateNext(queueIter);
diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
index 80da487a1358..7e0995c251b8 100644
--- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
@@ -588,7 +588,7 @@ public final class MessageQueue {
private static final AtomicLong mMessagesDelivered = new AtomicLong();
private boolean mMessageDirectlyQueued;
- private Message nextMessage(boolean peek) {
+ private Message nextMessage(boolean peek, boolean returnEarliest) {
int i = 0;
while (true) {
@@ -665,7 +665,7 @@ public final class MessageQueue {
* If we have a barrier we should return the async node (if it exists and is ready)
*/
if (msgNode != null && msgNode.isBarrier()) {
- if (asyncMsgNode != null && now >= asyncMsgNode.getWhen()) {
+ if (asyncMsgNode != null && (returnEarliest || now >= asyncMsgNode.getWhen())) {
found = asyncMsgNode;
} else {
next = asyncMsgNode;
@@ -679,7 +679,7 @@ public final class MessageQueue {
earliest = pickEarliestNode(msgNode, asyncMsgNode);
if (earliest != null) {
- if (now >= earliest.getWhen()) {
+ if (returnEarliest || now >= earliest.getWhen()) {
found = earliest;
} else {
next = earliest;
@@ -784,7 +784,7 @@ public final class MessageQueue {
mMessageDirectlyQueued = false;
nativePollOnce(ptr, mNextPollTimeoutMillis);
- Message msg = nextMessage(false);
+ Message msg = nextMessage(false, false);
if (msg != null) {
msg.markInUse();
return msg;
@@ -1089,7 +1089,7 @@ public final class MessageQueue {
*/
Long peekWhenForTest() {
throwIfNotTest();
- Message ret = nextMessage(true);
+ Message ret = nextMessage(true, true);
return ret != null ? ret.when : null;
}
@@ -1102,7 +1102,7 @@ public final class MessageQueue {
@Nullable
Message pollForTest() {
throwIfNotTest();
- return nextMessage(false);
+ return nextMessage(false, true);
}
/**
@@ -1116,7 +1116,7 @@ public final class MessageQueue {
throwIfNotTest();
// Call nextMessage to get the stack drained into our priority queues
- nextMessage(true);
+ nextMessage(true, false);
Iterator<MessageNode> queueIter = mPriorityQueue.iterator();
MessageNode queueNode = iterateNext(queueIter);
diff --git a/core/java/android/os/LegacyMessageQueue/MessageQueue.java b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
index cde2ba56fcba..132bdd1e56b8 100644
--- a/core/java/android/os/LegacyMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
@@ -759,27 +759,27 @@ public final class MessageQueue {
if (now >= msg.when) {
// Got a message.
mBlocked = false;
- if (prevMsg != null) {
- prevMsg.next = msg.next;
- if (prevMsg.next == null) {
- mLast = prevMsg;
- }
- } else {
- mMessages = msg.next;
- if (msg.next == null) {
- mLast = null;
- }
- }
- msg.next = null;
- msg.markInUse();
- if (msg.isAsynchronous()) {
- mAsyncMessageCount--;
+ }
+ if (prevMsg != null) {
+ prevMsg.next = msg.next;
+ if (prevMsg.next == null) {
+ mLast = prevMsg;
}
- if (TRACE) {
- Trace.setCounter("MQ.Delivered", mMessagesDelivered.incrementAndGet());
+ } else {
+ mMessages = msg.next;
+ if (msg.next == null) {
+ mLast = null;
}
- return msg;
}
+ msg.next = null;
+ msg.markInUse();
+ if (msg.isAsynchronous()) {
+ mAsyncMessageCount--;
+ }
+ if (TRACE) {
+ Trace.setCounter("MQ.Delivered", mMessagesDelivered.incrementAndGet());
+ }
+ return msg;
}
}
return null;
diff --git a/core/java/android/os/TestLooperManager.java b/core/java/android/os/TestLooperManager.java
index d451109554fa..ddfa3799706e 100644
--- a/core/java/android/os/TestLooperManager.java
+++ b/core/java/android/os/TestLooperManager.java
@@ -84,17 +84,8 @@ public class TestLooperManager {
* interactions with it have completed.
*/
public Message next() {
- // Wait for the looper block to come up, to make sure we don't accidentally get
- // the message for the block.
- while (!mLooperIsMyLooper && !mLooperBlocked) {
- synchronized (this) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
checkReleased();
+ waitForLooperHolder();
return mQueue.next();
}
@@ -110,6 +101,7 @@ public class TestLooperManager {
@Nullable
public Message poll() {
checkReleased();
+ waitForLooperHolder();
return mQueue.pollForTest();
}
@@ -124,6 +116,7 @@ public class TestLooperManager {
@Nullable
public Long peekWhen() {
checkReleased();
+ waitForLooperHolder();
return mQueue.peekWhenForTest();
}
@@ -133,6 +126,7 @@ public class TestLooperManager {
@FlaggedApi(Flags.FLAG_MESSAGE_QUEUE_TESTABILITY)
public boolean isBlockedOnSyncBarrier() {
checkReleased();
+ waitForLooperHolder();
return mQueue.isBlockedOnSyncBarrier();
}
@@ -221,6 +215,23 @@ public class TestLooperManager {
}
}
+ /**
+ * Waits until the Looper is blocked by the LooperHolder, if one was posted.
+ *
+ * After this method returns, it's guaranteed that the LooperHolder Message
+ * is not in the underlying queue.
+ */
+ private void waitForLooperHolder() {
+ while (!mLooperIsMyLooper && !mLooperBlocked) {
+ synchronized (this) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
private class LooperHolder implements Runnable {
@Override
public void run() {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 6c21dbf126bb..aaf6489d18ca 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3796,9 +3796,9 @@ public class UserManager {
@UnsupportedAppUsage
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
- @CachedProperty(modsFlagOnOrNone = {}, api = "is_user_unlocked")
+ @CachedProperty(api = "is_user_unlocked")
public boolean isUserUnlocked(@UserIdInt int userId) {
- return ((UserManagerCache) mIpcDataCache).isUserUnlocked(mService::isUserUnlocked, userId);
+ return UserManagerCache.isUserUnlocked(mService::isUserUnlocked, userId);
}
/** @hide */
@@ -3834,9 +3834,9 @@ public class UserManager {
/** @hide */
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
- @CachedProperty(modsFlagOnOrNone = {}, api = "is_user_unlocked")
+ @CachedProperty(api = "is_user_unlocked")
public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
- return ((UserManagerCache) mIpcDataCache)
+ return UserManagerCache
.isUserUnlockingOrUnlocked(mService::isUserUnlockingOrUnlocked, userId);
}
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index b12433a73a31..9e7c9f6e5417 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -198,6 +198,13 @@ flag {
}
flag {
+ name: "disable_madvise_artfile_default"
+ namespace: "system_performance"
+ description: "Disables madvise of .art files by default during app start."
+ bug: "382110550"
+}
+
+flag {
name: "disallow_cellular_null_ciphers_restriction"
namespace: "cellular_security"
description: "Guards a new UserManager user restriction that admins can use to require cellular encryption on their managed devices."
diff --git a/core/java/android/service/contextualsearch/OWNERS b/core/java/android/service/contextualsearch/OWNERS
index c435bd87be21..af2ed4daec11 100644
--- a/core/java/android/service/contextualsearch/OWNERS
+++ b/core/java/android/service/contextualsearch/OWNERS
@@ -1,3 +1,4 @@
srazdan@google.com
hyunyoungs@google.com
awickham@google.com
+rgl@google.com
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 09ebc9f030c2..1f1427df3925 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -66,7 +66,8 @@ public final class Adjustment implements Parcelable {
KEY_SENSITIVE_CONTENT,
KEY_RANKING_SCORE,
KEY_NOT_CONVERSATION,
- KEY_TYPE
+ KEY_TYPE,
+ KEY_SUMMARIZATION
})
@Retention(RetentionPolicy.SOURCE)
public @interface Keys {}
@@ -189,7 +190,7 @@ public final class Adjustment implements Parcelable {
TYPE_PROMOTION,
TYPE_SOCIAL_MEDIA,
TYPE_NEWS,
- TYPE_CONTENT_RECOMMENDATION
+ TYPE_CONTENT_RECOMMENDATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Types {}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 0a9276c34bfd..037292625d93 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -113,6 +113,8 @@ public abstract class NotificationAssistantService extends NotificationListenerS
* <p>
* Input: {@link #EXTRA_NOTIFICATION_KEY}, the {@link StatusBarNotification#getKey()} of the
* notification the user wants to file feedback for.
+ * Input: {@link #EXTRA_NOTIFICATION_ADJUSTMENT}, the {@link Adjustment} key that the user wants
+ * to file feedback about.
* <p>
* Output: Nothing.
*/
@@ -131,6 +133,16 @@ public abstract class NotificationAssistantService extends NotificationListenerS
= "android.service.notification.extra.NOTIFICATION_KEY";
/**
+ * A string extra containing the {@link Adjustment} key that the user wants to file feedback
+ * about.
+ *
+ * Extra for {@link #ACTION_NOTIFICATION_ASSISTANT_FEEDBACK_SETTINGS}.
+ */
+ @FlaggedApi(android.app.Flags.FLAG_NM_SUMMARIZATION)
+ public static final String EXTRA_NOTIFICATION_ADJUSTMENT
+ = "android.service.notification.extra.NOTIFICATION_ADJUSTMENT";
+
+ /**
* Data type: int, the feedback rating score provided by user. The score can be any integer
* value depends on the experimental and feedback UX design.
*/
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
index 177164296eea..6ed8c6d195e6 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
@@ -76,22 +76,30 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
private IQuickAccessWalletService mService;
@Nullable
- private final QuickAccessWalletServiceInfo mServiceInfo;
+ private QuickAccessWalletServiceInfo mServiceInfo;
private static final int MSG_TIMEOUT_SERVICE = 5;
QuickAccessWalletClientImpl(@NonNull Context context, @Nullable Executor bgExecutor) {
mContext = context.getApplicationContext();
- mServiceInfo = QuickAccessWalletServiceInfo.tryCreate(context);
+ mServiceInfo = null;
mHandler = new Handler(Looper.getMainLooper());
mLifecycleExecutor = (bgExecutor == null) ? Runnable::run : bgExecutor;
mRequestQueue = new ArrayDeque<>();
mEventListeners = new HashMap<>(1);
}
+ private QuickAccessWalletServiceInfo ensureServiceInfo() {
+ if (mServiceInfo == null) {
+ mServiceInfo = QuickAccessWalletServiceInfo.tryCreate(mContext);
+ }
+
+ return mServiceInfo;
+ }
+
@Override
public boolean isWalletServiceAvailable() {
- return mServiceInfo != null;
+ return ensureServiceInfo() != null;
}
@Override
@@ -239,12 +247,13 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
@Override
@Nullable
public Intent createWalletIntent() {
- if (mServiceInfo == null) {
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ if (serviceInfo == null) {
return null;
}
- String packageName = mServiceInfo.getComponentName().getPackageName();
- int userId = mServiceInfo.getUserId();
- String walletActivity = mServiceInfo.getWalletActivity();
+ String packageName = serviceInfo.getComponentName().getPackageName();
+ int userId = serviceInfo.getUserId();
+ String walletActivity = serviceInfo.getWalletActivity();
return createIntent(walletActivity, packageName, userId, ACTION_VIEW_WALLET);
}
@@ -298,11 +307,12 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
@Override
@Nullable
public Intent createWalletSettingsIntent() {
- if (mServiceInfo == null) {
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ if (serviceInfo == null) {
return null;
}
- String packageName = mServiceInfo.getComponentName().getPackageName();
- String settingsActivity = mServiceInfo.getSettingsActivity();
+ String packageName = serviceInfo.getComponentName().getPackageName();
+ String settingsActivity = serviceInfo.getSettingsActivity();
return createIntent(settingsActivity, packageName, UserHandle.myUserId(),
ACTION_VIEW_WALLET_SETTINGS);
}
@@ -356,36 +366,42 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
@Override
@Nullable
public Drawable getLogo() {
- return mServiceInfo == null ? null : mServiceInfo.getWalletLogo(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getWalletLogo(mContext);
}
@Nullable
@Override
public Drawable getTileIcon() {
- return mServiceInfo == null ? null : mServiceInfo.getTileIcon();
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getTileIcon();
}
@Nullable
@Override
public UserHandle getUser() {
- return mServiceInfo == null ? null : UserHandle.of(mServiceInfo.getUserId());
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : UserHandle.of(serviceInfo.getUserId());
}
@Override
@Nullable
public CharSequence getServiceLabel() {
- return mServiceInfo == null ? null : mServiceInfo.getServiceLabel(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getServiceLabel(mContext);
}
@Override
@Nullable
public CharSequence getShortcutShortLabel() {
- return mServiceInfo == null ? null : mServiceInfo.getShortcutShortLabel(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getShortcutShortLabel(mContext);
}
@Override
public CharSequence getShortcutLongLabel() {
- return mServiceInfo == null ? null : mServiceInfo.getShortcutLongLabel(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getShortcutLongLabel(mContext);
}
private void connect() {
@@ -393,7 +409,8 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
}
private void connectInternal() {
- if (mServiceInfo == null) {
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ if (serviceInfo == null) {
Log.w(TAG, "Wallet service unavailable");
return;
}
@@ -402,7 +419,7 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
}
mIsConnected = true;
Intent intent = new Intent(SERVICE_INTERFACE);
- intent.setComponent(mServiceInfo.getComponentName());
+ intent.setComponent(serviceInfo.getComponentName());
int flags = Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY;
mLifecycleExecutor.execute(() -> mContext.bindService(intent, this, flags));
resetServiceConnectionTimeout();
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 053ccdd73c8c..7c1e4976b9d3 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -372,8 +372,10 @@ public final class Choreographer {
/**
* @hide
+ * @deprecated Use vsync IDs with the regular Choreographer instead.
*/
@UnsupportedAppUsage
+ @Deprecated
public static Choreographer getSfInstance() {
return sSfThreadInstance.get();
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 2ec5dbc5612a..f58baffb1367 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -1146,14 +1146,6 @@ interface IWindowManager
*/
KeyboardShortcutGroup getApplicationLaunchKeyboardShortcuts(int deviceId);
- /*
- * Notifies about IME insets animation.
- *
- * @param running Indicates the insets animation state.
- * @param animationType Indicates the {@link InsetsController.AnimationType}
- */
- oneway void notifyImeInsetsAnimationStateChanged(boolean running, int animationType);
-
/**
* Returns whether the display with {@code displayId} ignores orientation request.
*/
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index e097a0764512..c174fbe0bbcd 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -214,14 +214,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
* Notifies when the state of running animation is changed. The state is either "running" or
* "idle".
*
- * @param running {@code true} if the given insets types start running
- * {@code false} otherwise.
- * @param animationType {@link AnimationType}
- * @param insetsTypes {@link Type}.
+ * @param running {@code true} if there is any animation running; {@code false} otherwise.
*/
- default void notifyAnimationRunningStateChanged(boolean running,
- @AnimationType int animationType, @InsetsType int insetsTypes) {
- }
+ default void notifyAnimationRunningStateChanged(boolean running) {}
/** @see ViewRootImpl#isHandlingPointerEvent */
default boolean isHandlingPointerEvent() {
@@ -749,8 +744,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
final InsetsAnimationControlRunner runner = new InsetsResizeAnimationRunner(
mFrame, mFromState, mToState, RESIZE_INTERPOLATOR,
ANIMATION_DURATION_RESIZE, mTypes, InsetsController.this);
- mHost.notifyAnimationRunningStateChanged(true,
- runner.getAnimationType(), mTypes);
+ if (mRunningAnimations.isEmpty()) {
+ mHost.notifyAnimationRunningStateChanged(true);
+ }
mRunningAnimations.add(new RunningAnimation(runner, runner.getAnimationType()));
}
};
@@ -1564,7 +1560,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
}
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
- mHost.notifyAnimationRunningStateChanged(true, animationType, types);
+ if (mRunningAnimations.isEmpty()) {
+ mHost.notifyAnimationRunningStateChanged(true);
+ }
mRunningAnimations.add(new RunningAnimation(runner, animationType));
if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
+ useInsetsAnimationThread);
@@ -1844,8 +1842,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
break;
}
}
- mHost.notifyAnimationRunningStateChanged(
- false, control.getAnimationType(), removedTypes);
+ if (mRunningAnimations.isEmpty()) {
+ mHost.notifyAnimationRunningStateChanged(false);
+ }
onAnimationStateChanged(removedTypes, false /* running */);
}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 3a0e6f187986..df680c054f56 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,6 +17,7 @@
package android.view;
import static android.app.Flags.notificationsRedesignTemplates;
+import static android.util.MathUtils.abs;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -60,6 +61,8 @@ public class NotificationHeaderView extends RelativeLayout {
private boolean mEntireHeaderClickable;
private boolean mExpandOnlyOnButton;
private boolean mAcceptAllTouches;
+ private float mTopLineTranslation;
+ private float mExpandButtonTranslation;
ViewOutlineProvider mProvider = new ViewOutlineProvider() {
@Override
@@ -205,6 +208,52 @@ public class NotificationHeaderView extends RelativeLayout {
mExpandButton.setLayoutParams(lp);
}
+ /** The view containing the app name, timestamp etc at the top of the notification. */
+ public NotificationTopLineView getTopLineView() {
+ return mTopLineView;
+ }
+
+ /** The view containing the button to expand the notification. */
+ public NotificationExpandButton getExpandButton() {
+ return mExpandButton;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ if (notificationsRedesignTemplates()) {
+ mTopLineTranslation = measureCenterTranslation(mTopLineView);
+ mExpandButtonTranslation = measureCenterTranslation(mExpandButton);
+ }
+ }
+
+ private float measureCenterTranslation(View view) {
+ // When the view is centered (see centerTopLine), its height is MATCH_PARENT
+ int parentHeight = getMeasuredHeight();
+ // When the view is top-aligned, its height is WRAP_CONTENT
+ float wrapContentHeight = view.getMeasuredHeight();
+ // Calculate the translation needed between the two alignments
+ final MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
+ return abs((parentHeight - wrapContentHeight) / 2f - lp.topMargin);
+ }
+
+ /**
+ * The vertical translation necessary between the two positions of the top line, to be used in
+ * the animation. See also {@link NotificationHeaderView#centerTopLine(boolean)}.
+ */
+ public float getTopLineTranslation() {
+ return mTopLineTranslation;
+ }
+
+ /**
+ * The vertical translation necessary between the two positions of the expander, to be used in
+ * the animation. See also {@link NotificationHeaderView#centerTopLine(boolean)}.
+ */
+ public float getExpandButtonTranslation() {
+ return mExpandButtonTranslation;
+ }
+
/**
* This is used to make the low-priority header show the bolded text of a title.
*
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7c5b300e9d24..bf34069f9445 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -24,7 +24,6 @@ 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;
import static android.os.Trace.TRACE_TAG_VIEW;
-import static android.service.autofill.Flags.improveFillDialogAconfig;
import static android.util.SequenceUtils.getInitSeq;
import static android.util.SequenceUtils.isIncomingSeqStale;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -923,8 +922,6 @@ public final class ViewRootImpl implements ViewParent,
private boolean mInsetsAnimationRunning;
- private int mInsetsAnimatingTypes = 0;
-
private long mPreviousFrameDrawnTime = -1;
// The largest view size percentage to the display size. Used on trace to collect metric.
private float mLargestChildPercentage = 0.0f;
@@ -2523,49 +2520,17 @@ public final class ViewRootImpl implements ViewParent,
* Notify the when the running state of a insets animation changed.
*/
@VisibleForTesting
- public void notifyInsetsAnimationRunningStateChanged(boolean running,
- @InsetsController.AnimationType int animationType,
- @InsetsType int insetsTypes) {
- @InsetsType int previousInsetsType = mInsetsAnimatingTypes;
- // If improveFillDialogAconfig is disabled, we notify WindowSession of all the updates we
- // receive here
- boolean notifyWindowSession = !improveFillDialogAconfig();
- if (running) {
- mInsetsAnimatingTypes |= insetsTypes;
- } else {
- mInsetsAnimatingTypes &= ~insetsTypes;
- }
+ public void notifyInsetsAnimationRunningStateChanged(boolean running) {
if (sToolkitSetFrameRateReadOnlyFlagValue) {
- mInsetsAnimationRunning = running;
- // If improveFillDialogAconfig is enabled, we need to confirm other animations aren't
- // running to maintain the existing behavior. System server were notified previously
- // only when animation started running or stopped when there were no running animations.
- if (improveFillDialogAconfig()) {
- if ((previousInsetsType == 0 && mInsetsAnimatingTypes != 0)
- || (previousInsetsType != 0 && mInsetsAnimatingTypes == 0)) {
- notifyWindowSession = true;
- }
- }
- if (notifyWindowSession) {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.instant(Trace.TRACE_TAG_VIEW,
- TextUtils.formatSimple("notifyInsetsAnimationRunningStateChanged(%s)",
- Boolean.toString(running)));
- }
- try {
- mWindowSession.notifyInsetsAnimationRunningStateChanged(mWindow, running);
- } catch (RemoteException e) {
- }
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.instant(Trace.TRACE_TAG_VIEW,
+ TextUtils.formatSimple("notifyInsetsAnimationRunningStateChanged(%s)",
+ Boolean.toString(running)));
}
- }
- if (improveFillDialogAconfig()) {
- // Update WindowManager for ImeAnimation
- if ((insetsTypes & WindowInsets.Type.ime()) != 0) {
- try {
- WindowManagerGlobal.getWindowManagerService()
- .notifyImeInsetsAnimationStateChanged(running, animationType);
- } catch (RemoteException e) {
- }
+ mInsetsAnimationRunning = running;
+ try {
+ mWindowSession.notifyInsetsAnimationRunningStateChanged(mWindow, running);
+ } catch (RemoteException e) {
}
}
}
@@ -5601,9 +5566,6 @@ public final class ViewRootImpl implements ViewParent,
if (mAttachInfo.mContentCaptureManager != null) {
ContentCaptureSession session =
mAttachInfo.mContentCaptureManager.getMainContentCaptureSession();
- if (android.view.contentcapture.flags.Flags.postCreateAndroidBgThread()) {
- session.performStart();
- }
session.notifyWindowBoundsChanged(session.getId(),
getConfiguration().windowConfiguration.getBounds());
}
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index f1666dbebd7b..889acca4b8b1 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -275,12 +275,9 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host {
}
@Override
- public void notifyAnimationRunningStateChanged(boolean running,
- @InsetsController.AnimationType int animationType,
- @WindowInsets.Type.InsetsType int insetsTypes) {
+ public void notifyAnimationRunningStateChanged(boolean running) {
if (mViewRoot != null) {
- mViewRoot.notifyInsetsAnimationRunningStateChanged(
- running, animationType, insetsTypes);
+ mViewRoot.notifyInsetsAnimationRunningStateChanged(running);
}
}
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index 6e2e1009fd40..8baa55f8e377 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -74,8 +74,8 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
}
@Override
- void internalFlush(@FlushReason int reason) {
- mParent.internalFlush(reason);
+ void flush(@FlushReason int reason) {
+ mParent.flush(reason);
}
@Override
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index b7a77d701045..724e8fa830af 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -52,6 +52,7 @@ import android.view.contentcapture.ContentCaptureSession.FlushReason;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.SyncResultReceiver;
@@ -604,6 +605,7 @@ public final class ContentCaptureManager {
mContext,
this,
prepareUiHandler(),
+ prepareContentCaptureHandler(),
mService
);
if (sVerbose) Log.v(TAG, "getMainContentCaptureSession(): created " + mMainSession);
@@ -614,6 +616,15 @@ public final class ContentCaptureManager {
@NonNull
@GuardedBy("mLock")
+ private Handler prepareContentCaptureHandler() {
+ if (mContentCaptureHandler == null) {
+ mContentCaptureHandler = BackgroundThread.getHandler();
+ }
+ return mContentCaptureHandler;
+ }
+
+ @NonNull
+ @GuardedBy("mLock")
private Handler prepareUiHandler() {
if (mUiHandler == null) {
mUiHandler = Handler.createAsync(Looper.getMainLooper());
@@ -663,7 +674,7 @@ public final class ContentCaptureManager {
@UiThread
public void flush(@FlushReason int reason) {
if (mOptions.lite) return;
- getMainContentCaptureSession().internalFlush(reason);
+ getMainContentCaptureSession().flush(reason);
}
/**
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 791a6f4254ec..9aeec20ec9b7 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -286,9 +286,6 @@ public abstract class ContentCaptureSession implements AutoCloseable {
abstract void start(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
@NonNull ComponentName component, int flags);
- /** @hide */
- public void performStart() {}
-
abstract boolean isDisabled();
/**
@@ -342,7 +339,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/**
* Flushes the buffered events to the service.
*/
- abstract void internalFlush(@FlushReason int reason);
+ abstract void flush(@FlushReason int reason);
/**
* Sets the {@link ContentCaptureContext} associated with the session.
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 29cae857098d..2fb78c038ca2 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -57,12 +57,10 @@ import android.view.View;
import android.view.ViewStructure;
import android.view.autofill.AutofillId;
import android.view.contentcapture.ViewNode.ViewStructureImpl;
-import android.view.contentcapture.flags.Flags;
import android.view.contentprotection.ContentProtectionEventProcessor;
import android.view.inputmethod.BaseInputConnection;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.os.IResultReceiver;
import com.android.modules.expresslog.Counter;
@@ -109,10 +107,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@NonNull
private final Handler mUiHandler;
- /** @hide */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- @Nullable
- public Handler mContentCaptureHandler;
+ @NonNull
+ private final Handler mContentCaptureHandler;
/**
* Interface to the system_server binder object - it's only used to start the session (and
@@ -191,12 +187,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@Nullable
public ContentProtectionEventProcessor mContentProtectionEventProcessor;
- /**
- * A runnable object to perform the start of this session.
- */
- @Nullable
- private Runnable mStartRunnable = null;
-
private static class SessionStateReceiver extends IResultReceiver.Stub {
private final WeakReference<MainContentCaptureSession> mMainSession;
@@ -208,7 +198,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
public void send(int resultCode, Bundle resultData) {
final MainContentCaptureSession mainSession = mMainSession.get();
if (mainSession == null) {
- Log.w(TAG, "received result after main session released");
+ Log.w(TAG, "received result after mina session released");
return;
}
final IBinder binder;
@@ -223,8 +213,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
binder = resultData.getBinder(EXTRA_BINDER);
if (binder == null) {
Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result");
- // explicitly init the bg thread
- mainSession.mContentCaptureHandler = mainSession.prepareContentCaptureHandler();
mainSession.runOnContentCaptureThread(() -> mainSession.resetSession(
STATE_DISABLED | STATE_INTERNAL_ERROR));
return;
@@ -232,45 +220,23 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
} else {
binder = null;
}
- // explicitly init the bg thread
- mainSession.mContentCaptureHandler = mainSession.prepareContentCaptureHandler();
mainSession.runOnContentCaptureThread(() ->
mainSession.onSessionStarted(resultCode, binder));
}
}
- /**
- * Prepares the content capture handler(i.e. the background thread).
- *
- * This is expected to be called from the {@link SessionStateReceiver#send} callback, after the
- * session {@link performStart}. This is expected to be executed in a binder thread, instead
- * of the UI thread.
- */
- @NonNull
- private Handler prepareContentCaptureHandler() {
- if (mContentCaptureHandler == null) {
- try {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareContentCaptureHandler");
- }
- mContentCaptureHandler = BackgroundThread.getHandler();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
- return mContentCaptureHandler;
- }
-
/** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public MainContentCaptureSession(
@NonNull ContentCaptureManager.StrippedContext context,
@NonNull ContentCaptureManager manager,
@NonNull Handler uiHandler,
+ @NonNull Handler contentCaptureHandler,
@NonNull IContentCaptureManager systemServerInterface) {
mContext = context;
mManager = manager;
mUiHandler = uiHandler;
+ mContentCaptureHandler = contentCaptureHandler;
mSystemServerInterface = systemServerInterface;
final int logHistorySize = mManager.mOptions.logHistorySize;
@@ -294,49 +260,18 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
/**
- * Performs the start of the session.
- *
- * This is expected to be called from the UI thread, when the activity finishes its first frame.
- * This is a no-op if the session has already been started.
- *
- * See {@link #start(IBinder, IBinder, ComponentName, int)} for more details.
- *
- * @hide */
- @Override
- public void performStart() {
- if (!hasStarted() && mStartRunnable != null) {
- mStartRunnable.run();
- }
- }
-
- /**
- * Creates a runnable to start this session.
- *
- * For performance reasons, it is better to only create a task to start the session
- * during the creation of the activity and perform the actual start when the activity
- * finishes it's first frame.
+ * Starts this session.
*/
@Override
void start(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
@NonNull ComponentName component, int flags) {
- if (Flags.postCreateAndroidBgThread()) {
- mStartRunnable = () -> {
- try {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "cc session startImpl");
- }
- startImpl(token, shareableActivityToken, component, flags);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- };
- } else {
- startImpl(token, shareableActivityToken, component, flags);
- }
+ runOnContentCaptureThread(
+ () -> startImpl(token, shareableActivityToken, component, flags));
}
private void startImpl(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
@NonNull ComponentName component, int flags) {
+ checkOnContentCaptureThread();
if (!isContentCaptureEnabled()) return;
if (sVerbose) {
@@ -370,12 +305,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
Log.w(TAG, "Error starting session for " + component.flattenToShortString() + ": " + e);
}
}
-
@Override
void onDestroy() {
clearAndRunOnContentCaptureThread(() -> {
try {
- internalFlush(FLUSH_REASON_SESSION_FINISHED);
+ flush(FLUSH_REASON_SESSION_FINISHED);
} finally {
destroySession();
}
@@ -623,10 +557,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
flushReason = forceFlush ? FLUSH_REASON_FORCE_FLUSH : FLUSH_REASON_FULL;
}
- internalFlush(flushReason);
+ flush(flushReason);
}
private boolean hasStarted() {
+ checkOnContentCaptureThread();
return mState != UNKNOWN_STATE;
}
@@ -640,11 +575,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
if (sVerbose) Log.v(TAG, "handleScheduleFlush(): session not started yet");
return;
}
- if (mContentCaptureHandler == null) {
- Log.w(TAG, "handleScheduleFlush(" + getDebugState(reason) + "): content capture "
- + "thread not ready");
- return;
- }
if (mDisabled.get()) {
// Should not be called on this state, as handleSendEvent checks.
@@ -687,18 +617,15 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
if (sVerbose) Log.v(TAG, "Nothing to flush");
return;
}
- internalFlush(reason);
+ flush(reason);
}
- /**
- * Internal API to flush the buffered events to the service.
- *
- * Do not confuse this with the public API {@link #flush()}.
- *
- * @hide */
+ /** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@Override
- public void internalFlush(@FlushReason int reason) {
+ public void flush(@FlushReason int reason) {
+ // TODO: b/380381249 renaming the internal APIs to prevent confusions between this and the
+ // public API.
runOnContentCaptureThread(() -> flushImpl(reason));
}
@@ -720,11 +647,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
if (!isContentCaptureReceiverEnabled()) {
return;
}
- if (mContentCaptureHandler == null) {
- Log.w(TAG, "handleForceFlush(" + getDebugState(reason) + "): content capture thread"
- + "not ready");
- return;
- }
if (mDirectServiceInterface == null) {
if (sVerbose) {
@@ -841,9 +763,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
mDirectServiceInterface = null;
mContentProtectionEventProcessor = null;
- if (mContentCaptureHandler != null) {
- mContentCaptureHandler.removeMessages(MSG_FLUSH);
- }
+ mContentCaptureHandler.removeMessages(MSG_FLUSH);
}
@Override
@@ -997,10 +917,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
* clear the buffer events then starting sending out current event.
*/
private void enqueueEvent(@NonNull final ContentCaptureEvent event, boolean forceFlush) {
- if (mContentCaptureHandler == null) {
- mEventProcessQueue.offer(event);
- return;
- }
if (forceFlush || mEventProcessQueue.size() >= mManager.mOptions.maxBufferSize - 1) {
// The buffer events are cleared in the same thread first to prevent new events
// being added during the time of context switch. This would disrupt the sequence
@@ -1203,10 +1119,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
* always delegate to the assigned thread from {@code mHandler} for synchronization.</p>
*/
private void checkOnContentCaptureThread() {
- if (mContentCaptureHandler == null) {
- Log.e(TAG, "content capture thread is not initiallized!");
- return;
- }
final boolean onContentCaptureThread = mContentCaptureHandler.getLooper().isCurrentThread();
if (!onContentCaptureThread) {
mWrongThreadCount.incrementAndGet();
@@ -1227,12 +1139,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
* </p>
*/
private void runOnContentCaptureThread(@NonNull Runnable r) {
- if (mContentCaptureHandler == null) {
- Log.e(TAG, "content capture thread is not initiallized!");
- // fall back to UI thread
- runOnUiThread(r);
- return;
- }
if (!mContentCaptureHandler.getLooper().isCurrentThread()) {
mContentCaptureHandler.post(r);
} else {
@@ -1241,12 +1147,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
private void clearAndRunOnContentCaptureThread(@NonNull Runnable r, int what) {
- if (mContentCaptureHandler == null) {
- Log.e(TAG, "content capture thread is not initiallized!");
- // fall back to UI thread
- runOnUiThread(r);
- return;
- }
if (!mContentCaptureHandler.getLooper().isCurrentThread()) {
mContentCaptureHandler.removeMessages(what);
mContentCaptureHandler.post(r);
diff --git a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
index 9df835098268..e7bc004ca2d2 100644
--- a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
+++ b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
@@ -15,14 +15,3 @@ flag {
bug: "380381249"
is_exported: true
}
-
-flag {
- name: "post_create_android_bg_thread"
- namespace: "pixel_state_server"
- description: "Feature flag to post create the bg thread when an app is in the allowlist"
- bug: "376468525"
- is_fixed_read_only: true
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e904345fb03e..0fb80422833c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -391,7 +391,8 @@ public final class InputMethodManager {
*/
@Deprecated
@GuardedBy("sLock")
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ publicAlternatives = "Use {@code Context#getSystemService(InputMethodManager.class)}.")
static InputMethodManager sInstance;
/**
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
index 4258ca4fde01..16f41146fd6b 100644
--- a/core/java/android/view/inputmethod/flags.aconfig
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -19,15 +19,6 @@ flag {
}
flag {
- name: "imm_userhandle_hostsidetests"
- is_exported: true
- namespace: "input_method"
- description: "Feature flag for replacing UserIdInt with UserHandle in some helper IMM functions"
- bug: "301713309"
- is_fixed_read_only: true
-}
-
-flag {
name: "concurrent_input_methods"
is_exported: true
namespace: "input_method"
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0e329c2859db..ec0d9152468e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -159,6 +159,7 @@ import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -719,6 +720,11 @@ public class RemoteViews implements Parcelable, Filter {
// Nothing to visit by default.
}
+ /** See {@link RemoteViews#visitIcons(Consumer)}. **/
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ // Nothing to visit by default.
+ }
+
public abstract void writeToParcel(Parcel dest, int flags);
/**
@@ -849,6 +855,29 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Note all {@link Icon} that are referenced internally.
+ * @hide
+ */
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ if (mActions != null) {
+ for (int i = 0; i < mActions.size(); i++) {
+ mActions.get(i).visitIcons(visitor);
+ }
+ }
+ if (mSizedRemoteViews != null) {
+ for (int i = 0; i < mSizedRemoteViews.size(); i++) {
+ mSizedRemoteViews.get(i).visitIcons(visitor);
+ }
+ }
+ if (mLandscape != null) {
+ mLandscape.visitIcons(visitor);
+ }
+ if (mPortrait != null) {
+ mPortrait.visitIcons(visitor);
+ }
+ }
+
+ /**
* @hide
* @return True if there is a change
*/
@@ -1312,6 +1341,19 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
+ public void visitIcons(Consumer<Icon> visitor) {
+ if (mItems == null) {
+ RemoteCollectionItems cachedItems = mCollectionCache.getItemsForId(mIntentId);
+ if (cachedItems != null) {
+ cachedItems.visitIcons(visitor);
+ }
+ return;
+ }
+
+ mItems.visitIcons(visitor);
+ }
+
+ @Override
public boolean canWriteToProto() {
// Skip actions that do not contain items (intent only actions)
return mItems != null;
@@ -2385,7 +2427,7 @@ public class RemoteViews implements Parcelable, Filter {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
ArrayList<Bitmap> mBitmaps;
SparseIntArray mBitmapHashes;
- int mBitmapMemory = -1;
+ long mBitmapMemory = -1;
public BitmapCache() {
mBitmaps = new ArrayList<>();
@@ -2449,7 +2491,7 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- public int getBitmapMemory() {
+ public long getBitmapMemory() {
if (mBitmapMemory < 0) {
mBitmapMemory = 0;
int count = mBitmaps.size();
@@ -2735,6 +2777,13 @@ public class RemoteViews implements Parcelable, Filter {
// TODO(b/281044385): Should we do anything about type BUNDLE?
}
}
+
+ @Override
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ if (mType == ICON && getParameterValue(null) instanceof Icon icon) {
+ visitor.accept(icon);
+ }
+ }
}
/** Class for the reflection actions. */
@@ -4139,6 +4188,11 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ mNestedViews.visitIcons(visitor);
+ }
+
+ @Override
public boolean canWriteToProto() {
return true;
}
@@ -6392,15 +6446,43 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
- * Returns an estimate of the bitmap heap memory usage for this RemoteViews.
+ * Returns an estimate of the bitmap heap memory usage by setBitmap and setImageViewBitmap in
+ * this RemoteViews.
+ *
+ * @hide
*/
- /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int estimateMemoryUsage() {
+ public long estimateMemoryUsage() {
return mBitmapCache.getBitmapMemory();
}
/**
+ * Returns an estimate of bitmap heap memory usage by setIcon and setImageViewIcon in this
+ * RemoteViews. Note that this function will count duplicate Icons in its estimate.
+ *
+ * @hide
+ */
+ public long estimateIconMemoryUsage() {
+ AtomicLong total = new AtomicLong(0);
+ visitIcons(icon -> {
+ if (icon.getType() == Icon.TYPE_BITMAP || icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
+ total.addAndGet(icon.getBitmap().getAllocationByteCount());
+ }
+ });
+ return total.get();
+ }
+
+ /**
+ * Returns an estimate of the bitmap heap memory usage for all Icon and Bitmap actions in this
+ * RemoteViews.
+ *
+ * @hide
+ */
+ public long estimateTotalBitmapMemoryUsage() {
+ return estimateMemoryUsage() + estimateIconMemoryUsage();
+ }
+
+ /**
* Add an action to be executed on the remote side when apply is called.
*
* @param a The action to add
@@ -9768,6 +9850,15 @@ public class RemoteViews implements Parcelable, Filter {
view.visitUris(visitor);
}
}
+
+ /**
+ * See {@link RemoteViews#visitIcons(Consumer)}.
+ */
+ private void visitIcons(@NonNull Consumer<Icon> visitor) {
+ for (RemoteViews view : mViews) {
+ view.visitIcons(visitor);
+ }
+ }
}
/**
diff --git a/core/java/android/window/DesktopExperienceFlags.java b/core/java/android/window/DesktopExperienceFlags.java
index 0d1bb77ae8a2..7758dea3ea8a 100644
--- a/core/java/android/window/DesktopExperienceFlags.java
+++ b/core/java/android/window/DesktopExperienceFlags.java
@@ -16,8 +16,6 @@
package android.window;
-import static com.android.server.display.feature.flags.Flags.enableDisplayContentModeManagement;
-
import android.annotation.Nullable;
import android.os.SystemProperties;
import android.util.Log;
@@ -42,7 +40,32 @@ import java.util.function.BooleanSupplier;
* @hide
*/
public enum DesktopExperienceFlags {
- ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT(() -> enableDisplayContentModeManagement(), true);
+ ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT(
+ com.android.server.display.feature.flags.Flags::enableDisplayContentModeManagement,
+ true),
+ ACTIVITY_EMBEDDING_SUPPORT_FOR_CONNECTED_DISPLAYS(
+ Flags::activityEmbeddingSupportForConnectedDisplays, false),
+ BASE_DENSITY_FOR_EXTERNAL_DISPLAYS(
+ com.android.server.display.feature.flags.Flags::baseDensityForExternalDisplays, true),
+ CONNECTED_DISPLAYS_CURSOR(com.android.input.flags.Flags::connectedDisplaysCursor, true),
+ DISPLAY_TOPOLOGY(com.android.server.display.feature.flags.Flags::displayTopology, true),
+ ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY(Flags::enableBugFixesForSecondaryDisplay, false),
+ ENABLE_CONNECTED_DISPLAYS_DND(Flags::enableConnectedDisplaysDnd, false),
+ ENABLE_CONNECTED_DISPLAYS_PIP(Flags::enableConnectedDisplaysPip, false),
+ ENABLE_CONNECTED_DISPLAYS_WINDOW_DRAG(Flags::enableConnectedDisplaysWindowDrag, false),
+ ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS(Flags::enableDisplayFocusInShellTransitions, false),
+ ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING(Flags::enableDisplayWindowingModeSwitching, false),
+ ENABLE_DRAG_TO_MAXIMIZE(Flags::enableDragToMaximize, true),
+ ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT(Flags::enableMoveToNextDisplayShortcut, false),
+ ENABLE_MULTIPLE_DESKTOPS_BACKEND(Flags::enableMultipleDesktopsBackend, false),
+ ENABLE_MULTIPLE_DESKTOPS_FRONTEND(Flags::enableMultipleDesktopsFrontend, false),
+ ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY(Flags::enablePerDisplayDesktopWallpaperActivity,
+ false),
+ ENABLE_PER_DISPLAY_PACKAGE_CONTEXT_CACHE_IN_STATUSBAR_NOTIF(
+ Flags::enablePerDisplayPackageContextCacheInStatusbarNotif, false),
+ ENTER_DESKTOP_BY_DEFAULT_ON_FREEFORM_DISPLAYS(Flags::enterDesktopByDefaultOnFreeformDisplays,
+ false),
+ REPARENT_WINDOW_TOKEN_API(Flags::reparentWindowTokenApi, true);
/**
* Flag class, to be used in case the enum cannot be used because the flag is not accessible.
@@ -55,7 +78,8 @@ public enum DesktopExperienceFlags {
// Whether the flag state should be affected by developer option.
private final boolean mShouldOverrideByDevOption;
- public DesktopExperienceFlag(BooleanSupplier flagFunction, boolean shouldOverrideByDevOption) {
+ public DesktopExperienceFlag(BooleanSupplier flagFunction,
+ boolean shouldOverrideByDevOption) {
this.mFlagFunction = flagFunction;
this.mShouldOverrideByDevOption = shouldOverrideByDevOption;
}
@@ -77,7 +101,8 @@ public enum DesktopExperienceFlags {
// Local cache for toggle override, which is initialized once on its first access. It needs to
// be refreshed only on reboots as overridden state is expected to take effect on reboots.
- @Nullable private static Boolean sCachedToggleOverride;
+ @Nullable
+ private static Boolean sCachedToggleOverride;
public static final String SYSTEM_PROPERTY_NAME = "persist.wm.debug.desktop_experience_devopts";
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index 82055afda8c1..3f2aa1ccecd8 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -35,10 +35,6 @@ import java.util.function.BooleanSupplier;
* windowing features which are aiming for developer preview before their release. It allows
* developer option to override the default behavior of these flags.
*
- * <p> The flags here will be controlled by either {@link
- * Settings.Global#DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATURES} or the {@code
- * persyst.wm.debug.desktop_experience_devopts} system property.
- *
* <p>NOTE: Flags should only be added to this enum when they have received Product and UX
* alignment that the feature is ready for developer preview, otherwise just do a flag check.
*
@@ -71,32 +67,35 @@ public enum DesktopModeFlags {
ENABLE_WINDOWING_EDGE_DRAG_RESIZE(Flags::enableWindowingEdgeDragResize, true),
ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS(
Flags::enableDesktopWindowingTaskbarRunningApps, true),
- // TODO: b/369763947 - remove this once ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS is ramped up
- ENABLE_DESKTOP_WINDOWING_TRANSITIONS(Flags::enableDesktopWindowingTransitions, false),
- ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS(
- Flags::enableDesktopWindowingEnterTransitions, false),
- ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS(Flags::enableDesktopWindowingExitTransitions, false),
ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS(
Flags::enableWindowingTransitionHandlersObservers, false),
- ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS(
- Flags::enableDesktopAppLaunchAlttabTransitions, false),
- ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS(
- Flags::enableDesktopAppLaunchTransitions, false),
ENABLE_DESKTOP_WINDOWING_PERSISTENCE(Flags::enableDesktopWindowingPersistence, false),
ENABLE_HANDLE_INPUT_FIX(Flags::enableHandleInputFix, true),
ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX(
- Flags::enableDesktopWindowingEnterTransitionBugfix, false),
+ Flags::enableDesktopWindowingEnterTransitionBugfix, true),
ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX(
- Flags::enableDesktopWindowingExitTransitionsBugfix, false),
+ Flags::enableDesktopWindowingExitTransitionsBugfix, true),
ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS_BUGFIX(
- Flags::enableDesktopAppLaunchAlttabTransitionsBugfix, false),
+ Flags::enableDesktopAppLaunchAlttabTransitionsBugfix, true),
ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX(
- Flags::enableDesktopAppLaunchTransitionsBugfix, false),
+ Flags::enableDesktopAppLaunchTransitionsBugfix, true),
+ ENABLE_DESKTOP_COMPAT_UI_VISIBILITY_STATUS(
+ Flags::enableCompatUiVisibilityStatus, true),
+ ENABLE_DESKTOP_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE_BUGFIX(
+ Flags::skipCompatUiEducationInDesktopMode, true),
INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC(
Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true),
+ ENABLE_DESKTOP_WINDOWING_HSUM(Flags::enableDesktopWindowingHsum, true),
ENABLE_MINIMIZE_BUTTON(Flags::enableMinimizeButton, true),
ENABLE_RESIZING_METRICS(Flags::enableResizingMetrics, true),
- ENABLE_TASK_RESIZING_KEYBOARD_SHORTCUTS(Flags::enableTaskResizingKeyboardShortcuts, true);
+ ENABLE_TASK_RESIZING_KEYBOARD_SHORTCUTS(Flags::enableTaskResizingKeyboardShortcuts, true),
+ ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER(
+ Flags::enableDesktopWallpaperActivityForSystemUser, true),
+ ENABLE_TOP_VISIBLE_ROOT_TASK_PER_USER_TRACKING(
+ Flags::enableTopVisibleRootTaskPerUserTracking, true),
+ ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX(
+ Flags::enableDesktopRecentsTransitionsCornersBugfix, false),
+ ENABLE_DESKTOP_SYSTEM_DIALOGS_TRANSITIONS(Flags::enableDesktopSystemDialogsTransitions, true);
/**
* Flag class, to be used in case the enum cannot be used because the flag is not accessible.
@@ -116,7 +115,7 @@ public enum DesktopModeFlags {
/**
* Determines state of flag based on the actual flag and desktop mode developer option
- * or desktop experience developer option overrides.
+ * overrides.
*/
public boolean isTrue() {
return isFlagTrue(mFlagFunction, mShouldOverrideByDevOption);
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index ce0ccd5c6d0d..68b5a261f507 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -112,6 +112,12 @@ public final class WindowContainerTransaction implements Parcelable {
mTaskFragmentOrganizer = null;
}
+ /*
+ * ===========================================================================================
+ * Window container properties
+ * ===========================================================================================
+ */
+
/**
* Resize a container.
*/
@@ -170,20 +176,6 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
- * Notify {@link com.android.server.wm.PinnedTaskController} that the picture-in-picture task
- * has finished the enter animation with the given bounds.
- */
- @NonNull
- public WindowContainerTransaction scheduleFinishEnterPip(
- @NonNull WindowContainerToken container, @NonNull Rect bounds) {
- final Change chg = getOrCreateChange(container.asBinder());
- chg.mPinnedBounds = new Rect(bounds);
- chg.mChangeMask |= Change.CHANGE_PIP_CALLBACK;
-
- return this;
- }
-
- /**
* Send a SurfaceControl transaction to the server, which the server will apply in sync with
* the next bounds change. As this uses deferred transaction and not BLAST it is only
* able to sync with a single window, and the first visible window in this hierarchy of type
@@ -204,36 +196,6 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
- * Like {@link #setBoundsChangeTransaction} but instead queues up a setPosition/WindowCrop
- * on a container's surface control. This is useful when a boundsChangeTransaction needs to be
- * queued up on a Task that won't be organized until the end of this window-container
- * transaction.
- *
- * This requires that, at the end of this transaction, `task` will be organized; otherwise
- * the server will throw an IllegalArgumentException.
- *
- * WARNING: Use this carefully. Whatever is set here should match the expected bounds after
- * the transaction completes since it will likely be replaced by it. This call is
- * intended to pre-emptively set bounds on a surface in sync with a buffer when
- * otherwise the new bounds and the new buffer would update on different frames.
- *
- * TODO(b/134365562): remove once TaskOrg drives full-screen or BLAST is enabled.
- *
- * @hide
- */
- @NonNull
- public WindowContainerTransaction setBoundsChangeTransaction(
- @NonNull WindowContainerToken task, @NonNull Rect surfaceBounds) {
- Change chg = getOrCreateChange(task.asBinder());
- if (chg.mBoundsChangeSurfaceBounds == null) {
- chg.mBoundsChangeSurfaceBounds = new Rect();
- }
- chg.mBoundsChangeSurfaceBounds.set(surfaceBounds);
- chg.mChangeMask |= Change.CHANGE_BOUNDS_TRANSACTION_RECT;
- return this;
- }
-
- /**
* Set the windowing mode of children of a given root task, without changing
* the windowing mode of the Task itself. This can be used during transitions
* for example to make the activity render it's fullscreen configuration
@@ -381,22 +343,115 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
- * Reparents a container into another one. The effect of a {@code null} parent can vary. For
- * example, reparenting a stack to {@code null} will reparent it to its display.
+ * Sets whether a container is being drag-resized.
+ * When {@code true}, the client will reuse a single (larger) surface size to avoid
+ * continuous allocations on every size change.
*
- * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
- * the bottom.
+ * @param container WindowContainerToken of the task that changed its drag resizing state
+ * @hide
*/
@NonNull
- public WindowContainerTransaction reparent(@NonNull WindowContainerToken child,
- @Nullable WindowContainerToken parent, boolean onTop) {
- mHierarchyOps.add(HierarchyOp.createForReparent(child.asBinder(),
- parent == null ? null : parent.asBinder(),
- onTop));
+ public WindowContainerTransaction setDragResizing(@NonNull WindowContainerToken container,
+ boolean dragResizing) {
+ final Change change = getOrCreateChange(container.asBinder());
+ change.mChangeMask |= Change.CHANGE_DRAG_RESIZING;
+ change.mDragResizing = dragResizing;
return this;
}
/**
+ * Sets/removes the always on top flag for this {@code windowContainer}. See
+ * {@link com.android.server.wm.ConfigurationContainer#setAlwaysOnTop(boolean)}.
+ * Please note that this method is only intended to be used for a
+ * {@link com.android.server.wm.Task} or {@link com.android.server.wm.DisplayArea}.
+ *
+ * <p>
+ * Setting always on top to {@code True} will also make the {@code windowContainer} to move
+ * to the top.
+ * </p>
+ * <p>
+ * Setting always on top to {@code False} will make this {@code windowContainer} to move
+ * below the other always on top sibling containers.
+ * </p>
+ *
+ * @param windowContainer the container which the flag need to be updated for.
+ * @param alwaysOnTop denotes whether or not always on top flag should be set.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction setAlwaysOnTop(
+ @NonNull WindowContainerToken windowContainer, boolean alwaysOnTop) {
+ final HierarchyOp hierarchyOp =
+ new HierarchyOp.Builder(
+ HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP)
+ .setContainer(windowContainer.asBinder())
+ .setAlwaysOnTop(alwaysOnTop)
+ .build();
+ mHierarchyOps.add(hierarchyOp);
+ return this;
+ }
+
+ /**
+ * Sets/removes the reparent leaf task flag for this {@code windowContainer}.
+ * When this is set, the server side will try to reparent the leaf task to task display area
+ * if there is an existing activity in history during the activity launch. This operation only
+ * support on the organized root task.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction setReparentLeafTaskIfRelaunch(
+ @NonNull WindowContainerToken windowContainer, boolean reparentLeafTaskIfRelaunch) {
+ final HierarchyOp hierarchyOp =
+ new HierarchyOp.Builder(
+ HierarchyOp.HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH)
+ .setContainer(windowContainer.asBinder())
+ .setReparentLeafTaskIfRelaunch(reparentLeafTaskIfRelaunch)
+ .build();
+ mHierarchyOps.add(hierarchyOp);
+ return this;
+ }
+
+ /**
+ * Defers client-facing configuration changes for activities in `container` until the end of
+ * the transition animation. The configuration will still be applied to the WMCore hierarchy
+ * at the normal time (beginning); so, special consideration must be made for this in the
+ * animation.
+ *
+ * @param container WindowContainerToken who's children should defer config notification.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction deferConfigToTransitionEnd(
+ @NonNull WindowContainerToken container) {
+ final Change change = getOrCreateChange(container.asBinder());
+ change.mConfigAtTransitionEnd = true;
+ return this;
+ }
+
+ /**
+ * Sets the task as trimmable or not. This can be used to prevent the task from being trimmed by
+ * recents. This attribute is set to true on task creation by default.
+ *
+ * @param isTrimmableFromRecents When {@code true}, task is set as trimmable from recents.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction setTaskTrimmableFromRecents(
+ @NonNull WindowContainerToken container,
+ boolean isTrimmableFromRecents) {
+ mHierarchyOps.add(
+ HierarchyOp.createForSetTaskTrimmableFromRecents(container.asBinder(),
+ isTrimmableFromRecents));
+ return this;
+ }
+
+ /*
+ * ===========================================================================================
+ * Hierarchy updates (create/destroy/reorder/reparent containers)
+ * ===========================================================================================
+ */
+
+ /**
* Reorders a container within its parent.
*
* @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
@@ -425,6 +480,22 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
+ * Reparents a container into another one. The effect of a {@code null} parent can vary. For
+ * example, reparenting a stack to {@code null} will reparent it to its display.
+ *
+ * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
+ * the bottom.
+ */
+ @NonNull
+ public WindowContainerTransaction reparent(@NonNull WindowContainerToken child,
+ @Nullable WindowContainerToken parent, boolean onTop) {
+ mHierarchyOps.add(HierarchyOp.createForReparent(child.asBinder(),
+ parent == null ? null : parent.asBinder(),
+ onTop));
+ return this;
+ }
+
+ /**
* Reparent's all children tasks or the top task of {@param currentParent} in the specified
* {@param windowingMode} and {@param activityType} to {@param newParent} in their current
* z-order.
@@ -478,6 +549,116 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
+ * Finds and removes a task and its children using its container token. The task is removed
+ * from recents.
+ *
+ * If the task is a root task, its leaves are removed but the root task is not. Use
+ * {@link #removeRootTask(WindowContainerToken)} to remove the root task.
+ *
+ * @param containerToken ContainerToken of Task to be removed
+ */
+ @NonNull
+ public WindowContainerTransaction removeTask(@NonNull WindowContainerToken containerToken) {
+ mHierarchyOps.add(HierarchyOp.createForRemoveTask(containerToken.asBinder()));
+ return this;
+ }
+
+ /**
+ * Finds and removes a root task created by an organizer and its leaves using its container
+ * token.
+ *
+ * @param containerToken ContainerToken of the root task to be removed
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction removeRootTask(@NonNull WindowContainerToken containerToken) {
+ mHierarchyOps.add(HierarchyOp.createForRemoveRootTask(containerToken.asBinder()));
+ return this;
+ }
+
+ /**
+ * If `container` was brought to front as a transient-launch (eg. recents), this will reorder
+ * the container back to where it was prior to the transient-launch. This way if a transient
+ * launch is "aborted", the z-ordering of containers in WM should be restored to before the
+ * launch.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction restoreTransientOrder(
+ @NonNull WindowContainerToken container) {
+ final HierarchyOp hierarchyOp =
+ new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER)
+ .setContainer(container.asBinder())
+ .build();
+ mHierarchyOps.add(hierarchyOp);
+ return this;
+ }
+
+ /**
+ * Restore the back navigation target from visible to invisible for canceling gesture animation.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction restoreBackNavi() {
+ final HierarchyOp hierarchyOp =
+ new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION)
+ .build();
+ mHierarchyOps.add(hierarchyOp);
+ return this;
+ }
+
+ /*
+ * ===========================================================================================
+ * Activity launch
+ * ===========================================================================================
+ */
+
+ /**
+ * Starts a task by id. The task is expected to already exist (eg. as a recent task).
+ * @param taskId Id of task to start.
+ * @param options bundle containing ActivityOptions for the task's top activity.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction startTask(int taskId, @Nullable Bundle options) {
+ mHierarchyOps.add(HierarchyOp.createForTaskLaunch(taskId, options));
+ return this;
+ }
+
+ /**
+ * Sends a pending intent in sync.
+ * @param sender The PendingIntent sender.
+ * @param intent The fillIn intent to patch over the sender's base intent.
+ * @param options bundle containing ActivityOptions for the task's top activity.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction sendPendingIntent(@Nullable PendingIntent sender,
+ @Nullable Intent intent, @Nullable Bundle options) {
+ mHierarchyOps.add(new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT)
+ .setLaunchOptions(options)
+ .setPendingIntent(sender)
+ .setActivityIntent(intent)
+ .build());
+ return this;
+ }
+
+ /**
+ * Starts activity(s) from a shortcut.
+ * @param callingPackage The package launching the shortcut.
+ * @param shortcutInfo Information about the shortcut to start
+ * @param options bundle containing ActivityOptions for the task's top activity.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction startShortcut(@NonNull String callingPackage,
+ @NonNull ShortcutInfo shortcutInfo, @Nullable Bundle options) {
+ mHierarchyOps.add(HierarchyOp.createForStartShortcut(
+ callingPackage, shortcutInfo, options));
+ return this;
+ }
+
+ /**
* Sets whether a container should be the launch root for the specified windowing mode and
* activity type. This currently only applies to Task containers created by organizer.
*/
@@ -491,6 +672,12 @@ public final class WindowContainerTransaction implements Parcelable {
return this;
}
+ /*
+ * ===========================================================================================
+ * Multitasking
+ * ===========================================================================================
+ */
+
/**
* Sets two containers adjacent to each other. Containers below two visible adjacent roots will
* be made invisible. This currently only applies to TaskFragment containers created by
@@ -599,93 +786,162 @@ public final class WindowContainerTransaction implements Parcelable {
return this;
}
+ /*
+ * ===========================================================================================
+ * PIP
+ * ===========================================================================================
+ */
+
/**
- * Starts a task by id. The task is expected to already exist (eg. as a recent task).
- * @param taskId Id of task to start.
- * @param options bundle containing ActivityOptions for the task's top activity.
+ * Moves the PiP activity of a parent task to a pinned root task.
+ * @param parentToken the parent task of the PiP activity
+ * @param bounds the entry bounds
* @hide
*/
@NonNull
- public WindowContainerTransaction startTask(int taskId, @Nullable Bundle options) {
- mHierarchyOps.add(HierarchyOp.createForTaskLaunch(taskId, options));
+ public WindowContainerTransaction movePipActivityToPinnedRootTask(
+ @NonNull WindowContainerToken parentToken, @NonNull Rect bounds) {
+ mHierarchyOps.add(new HierarchyOp
+ .Builder(HierarchyOp.HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK)
+ .setContainer(parentToken.asBinder())
+ .setBounds(bounds)
+ .build());
return this;
}
/**
- * Finds and removes a task and its children using its container token. The task is removed
- * from recents.
- *
- * If the task is a root task, its leaves are removed but the root task is not. Use
- * {@link #removeRootTask(WindowContainerToken)} to remove the root task.
- *
- * @param containerToken ContainerToken of Task to be removed
+ * Notify {@link com.android.server.wm.PinnedTaskController} that the picture-in-picture task
+ * has finished the enter animation with the given bounds.
*/
@NonNull
- public WindowContainerTransaction removeTask(@NonNull WindowContainerToken containerToken) {
- mHierarchyOps.add(HierarchyOp.createForRemoveTask(containerToken.asBinder()));
+ public WindowContainerTransaction scheduleFinishEnterPip(
+ @NonNull WindowContainerToken container, @NonNull Rect bounds) {
+ final Change chg = getOrCreateChange(container.asBinder());
+ chg.mPinnedBounds = new Rect(bounds);
+ chg.mChangeMask |= Change.CHANGE_PIP_CALLBACK;
+
return this;
}
+ /*
+ * ===========================================================================================
+ * Insets
+ * ===========================================================================================
+ */
+
/**
- * Finds and removes a root task created by an organizer and its leaves using its container
- * token.
+ * Adds a given {@code Rect} as an insets source frame on the {@code receiver}.
*
- * @param containerToken ContainerToken of the root task to be removed
+ * @param receiver The window container that the insets source is added to.
+ * @param owner The owner of the insets source. An insets source can only be modified by its
+ * owner.
+ * @param index An owner might add multiple insets sources with the same type.
+ * This identifies them.
+ * @param type The {@link InsetsType} of the insets source.
+ * @param frame The rectangle area of the insets source.
+ * @param boundingRects The bounding rects within this inset, relative to the |frame|.
* @hide
*/
@NonNull
- public WindowContainerTransaction removeRootTask(@NonNull WindowContainerToken containerToken) {
- mHierarchyOps.add(HierarchyOp.createForRemoveRootTask(containerToken.asBinder()));
+ public WindowContainerTransaction addInsetsSource(
+ @NonNull WindowContainerToken receiver,
+ @Nullable IBinder owner, int index, @InsetsType int type, @Nullable Rect frame,
+ @Nullable Rect[] boundingRects, @InsetsSource.Flags int flags) {
+ final HierarchyOp hierarchyOp =
+ new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER)
+ .setContainer(receiver.asBinder())
+ .setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type)
+ .setSource(InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE)
+ .setArbitraryRectangle(frame)
+ .setBoundingRects(boundingRects)
+ .setFlags(flags))
+ .setInsetsFrameOwner(owner)
+ .build();
+ mHierarchyOps.add(hierarchyOp);
return this;
}
/**
- * Sets whether a container is being drag-resized.
- * When {@code true}, the client will reuse a single (larger) surface size to avoid
- * continuous allocations on every size change.
+ * Removes the insets source from the {@code receiver}.
*
- * @param container WindowContainerToken of the task that changed its drag resizing state
+ * @param receiver The window container that the insets source was added to.
+ * @param owner The owner of the insets source. An insets source can only be modified by its
+ * owner.
+ * @param index An owner might add multiple insets sources with the same type.
+ * This identifies them.
+ * @param type The {@link InsetsType} of the insets source.
* @hide
*/
@NonNull
- public WindowContainerTransaction setDragResizing(@NonNull WindowContainerToken container,
- boolean dragResizing) {
- final Change change = getOrCreateChange(container.asBinder());
- change.mChangeMask |= Change.CHANGE_DRAG_RESIZING;
- change.mDragResizing = dragResizing;
+ public WindowContainerTransaction removeInsetsSource(@NonNull WindowContainerToken receiver,
+ @Nullable IBinder owner, int index, @InsetsType int type) {
+ final HierarchyOp hierarchyOp =
+ new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER)
+ .setContainer(receiver.asBinder())
+ .setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type))
+ .setInsetsFrameOwner(owner)
+ .build();
+ mHierarchyOps.add(hierarchyOp);
return this;
}
+ /*
+ * ===========================================================================================
+ * Keyguard
+ * ===========================================================================================
+ */
+
/**
- * Sends a pending intent in sync.
- * @param sender The PendingIntent sender.
- * @param intent The fillIn intent to patch over the sender's base intent.
- * @param options bundle containing ActivityOptions for the task's top activity.
+ * Adds a {@link KeyguardState} to apply to the given displays.
+ *
* @hide
*/
@NonNull
- public WindowContainerTransaction sendPendingIntent(@Nullable PendingIntent sender,
- @Nullable Intent intent, @Nullable Bundle options) {
- mHierarchyOps.add(new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT)
- .setLaunchOptions(options)
- .setPendingIntent(sender)
- .setActivityIntent(intent)
- .build());
+ public WindowContainerTransaction addKeyguardState(@NonNull KeyguardState keyguardState) {
+ Objects.requireNonNull(keyguardState);
+ final HierarchyOp hierarchyOp =
+ new HierarchyOp.Builder(
+ HierarchyOp.HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE)
+ .setKeyguardState(keyguardState)
+ .build();
+ mHierarchyOps.add(hierarchyOp);
return this;
}
+ /*
+ * ===========================================================================================
+ * Task fragments
+ * ===========================================================================================
+ */
+
/**
- * Starts activity(s) from a shortcut.
- * @param callingPackage The package launching the shortcut.
- * @param shortcutInfo Information about the shortcut to start
- * @param options bundle containing ActivityOptions for the task's top activity.
+ * Sets the {@link TaskFragmentOrganizer} that applies this {@link WindowContainerTransaction}.
+ * When this is set, the server side will not check for the permission of
+ * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, but will ensure this WCT only
+ * contains operations that are allowed for this organizer, such as modifying TaskFragments that
+ * are organized by this organizer.
* @hide
*/
@NonNull
- public WindowContainerTransaction startShortcut(@NonNull String callingPackage,
- @NonNull ShortcutInfo shortcutInfo, @Nullable Bundle options) {
- mHierarchyOps.add(HierarchyOp.createForStartShortcut(
- callingPackage, shortcutInfo, options));
+ public WindowContainerTransaction setTaskFragmentOrganizer(
+ @NonNull ITaskFragmentOrganizer organizer) {
+ mTaskFragmentOrganizer = organizer;
+ return this;
+ }
+
+ /**
+ * When this {@link WindowContainerTransaction} failed to finish on the server side, it will
+ * trigger callback with this {@param errorCallbackToken}.
+ * @param errorCallbackToken client provided token that will be passed back as parameter in
+ * the callback if there is an error on the server side.
+ * @see ITaskFragmentOrganizer#onTaskFragmentError
+ */
+ @NonNull
+ public WindowContainerTransaction setErrorCallbackToken(@NonNull IBinder errorCallbackToken) {
+ if (mErrorCallbackToken != null) {
+ throw new IllegalStateException("Can't set multiple error token for one transaction.");
+ }
+ mErrorCallbackToken = errorCallbackToken;
return this;
}
@@ -793,93 +1049,6 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
- * If `container` was brought to front as a transient-launch (eg. recents), this will reorder
- * the container back to where it was prior to the transient-launch. This way if a transient
- * launch is "aborted", the z-ordering of containers in WM should be restored to before the
- * launch.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction restoreTransientOrder(
- @NonNull WindowContainerToken container) {
- final HierarchyOp hierarchyOp =
- new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER)
- .setContainer(container.asBinder())
- .build();
- mHierarchyOps.add(hierarchyOp);
- return this;
- }
-
- /**
- * Restore the back navigation target from visible to invisible for canceling gesture animation.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction restoreBackNavi() {
- final HierarchyOp hierarchyOp =
- new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION)
- .build();
- mHierarchyOps.add(hierarchyOp);
- return this;
- }
-
- /**
- * Adds a given {@code Rect} as an insets source frame on the {@code receiver}.
- *
- * @param receiver The window container that the insets source is added to.
- * @param owner The owner of the insets source. An insets source can only be modified by its
- * owner.
- * @param index An owner might add multiple insets sources with the same type.
- * This identifies them.
- * @param type The {@link InsetsType} of the insets source.
- * @param frame The rectangle area of the insets source.
- * @param boundingRects The bounding rects within this inset, relative to the |frame|.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction addInsetsSource(
- @NonNull WindowContainerToken receiver,
- @Nullable IBinder owner, int index, @InsetsType int type, @Nullable Rect frame,
- @Nullable Rect[] boundingRects, @InsetsSource.Flags int flags) {
- final HierarchyOp hierarchyOp =
- new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER)
- .setContainer(receiver.asBinder())
- .setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type)
- .setSource(InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE)
- .setArbitraryRectangle(frame)
- .setBoundingRects(boundingRects)
- .setFlags(flags))
- .setInsetsFrameOwner(owner)
- .build();
- mHierarchyOps.add(hierarchyOp);
- return this;
- }
-
- /**
- * Removes the insets source from the {@code receiver}.
- *
- * @param receiver The window container that the insets source was added to.
- * @param owner The owner of the insets source. An insets source can only be modified by its
- * owner.
- * @param index An owner might add multiple insets sources with the same type.
- * This identifies them.
- * @param type The {@link InsetsType} of the insets source.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction removeInsetsSource(@NonNull WindowContainerToken receiver,
- @Nullable IBinder owner, int index, @InsetsType int type) {
- final HierarchyOp hierarchyOp =
- new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER)
- .setContainer(receiver.asBinder())
- .setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type))
- .setInsetsFrameOwner(owner)
- .build();
- mHierarchyOps.add(hierarchyOp);
- return this;
- }
-
- /**
* Requests focus on the top running Activity in the given TaskFragment. This will only take
* effect if there is no focus, or if the current focus is in the same Task as the requested
* TaskFragment.
@@ -961,157 +1130,6 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
- * Adds a {@link KeyguardState} to apply to the given displays.
- *
- * @hide
- */
- @NonNull
- public WindowContainerTransaction addKeyguardState(@NonNull KeyguardState keyguardState) {
- Objects.requireNonNull(keyguardState);
- final HierarchyOp hierarchyOp =
- new HierarchyOp.Builder(
- HierarchyOp.HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE)
- .setKeyguardState(keyguardState)
- .build();
- mHierarchyOps.add(hierarchyOp);
- return this;
- }
-
- /**
- * Sets/removes the always on top flag for this {@code windowContainer}. See
- * {@link com.android.server.wm.ConfigurationContainer#setAlwaysOnTop(boolean)}.
- * Please note that this method is only intended to be used for a
- * {@link com.android.server.wm.Task} or {@link com.android.server.wm.DisplayArea}.
- *
- * <p>
- * Setting always on top to {@code True} will also make the {@code windowContainer} to move
- * to the top.
- * </p>
- * <p>
- * Setting always on top to {@code False} will make this {@code windowContainer} to move
- * below the other always on top sibling containers.
- * </p>
- *
- * @param windowContainer the container which the flag need to be updated for.
- * @param alwaysOnTop denotes whether or not always on top flag should be set.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction setAlwaysOnTop(
- @NonNull WindowContainerToken windowContainer, boolean alwaysOnTop) {
- final HierarchyOp hierarchyOp =
- new HierarchyOp.Builder(
- HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP)
- .setContainer(windowContainer.asBinder())
- .setAlwaysOnTop(alwaysOnTop)
- .build();
- mHierarchyOps.add(hierarchyOp);
- return this;
- }
-
- /**
- * When this {@link WindowContainerTransaction} failed to finish on the server side, it will
- * trigger callback with this {@param errorCallbackToken}.
- * @param errorCallbackToken client provided token that will be passed back as parameter in
- * the callback if there is an error on the server side.
- * @see ITaskFragmentOrganizer#onTaskFragmentError
- */
- @NonNull
- public WindowContainerTransaction setErrorCallbackToken(@NonNull IBinder errorCallbackToken) {
- if (mErrorCallbackToken != null) {
- throw new IllegalStateException("Can't set multiple error token for one transaction.");
- }
- mErrorCallbackToken = errorCallbackToken;
- return this;
- }
-
- /**
- * Sets the {@link TaskFragmentOrganizer} that applies this {@link WindowContainerTransaction}.
- * When this is set, the server side will not check for the permission of
- * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, but will ensure this WCT only
- * contains operations that are allowed for this organizer, such as modifying TaskFragments that
- * are organized by this organizer.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction setTaskFragmentOrganizer(
- @NonNull ITaskFragmentOrganizer organizer) {
- mTaskFragmentOrganizer = organizer;
- return this;
- }
-
- /**
- * Sets/removes the reparent leaf task flag for this {@code windowContainer}.
- * When this is set, the server side will try to reparent the leaf task to task display area
- * if there is an existing activity in history during the activity launch. This operation only
- * support on the organized root task.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction setReparentLeafTaskIfRelaunch(
- @NonNull WindowContainerToken windowContainer, boolean reparentLeafTaskIfRelaunch) {
- final HierarchyOp hierarchyOp =
- new HierarchyOp.Builder(
- HierarchyOp.HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH)
- .setContainer(windowContainer.asBinder())
- .setReparentLeafTaskIfRelaunch(reparentLeafTaskIfRelaunch)
- .build();
- mHierarchyOps.add(hierarchyOp);
- return this;
- }
-
- /**
- * Moves the PiP activity of a parent task to a pinned root task.
- * @param parentToken the parent task of the PiP activity
- * @param bounds the entry bounds
- * @hide
- */
- @NonNull
- public WindowContainerTransaction movePipActivityToPinnedRootTask(
- @NonNull WindowContainerToken parentToken, @NonNull Rect bounds) {
- mHierarchyOps.add(new HierarchyOp
- .Builder(HierarchyOp.HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK)
- .setContainer(parentToken.asBinder())
- .setBounds(bounds)
- .build());
- return this;
- }
-
- /**
- * Defers client-facing configuration changes for activities in `container` until the end of
- * the transition animation. The configuration will still be applied to the WMCore hierarchy
- * at the normal time (beginning); so, special consideration must be made for this in the
- * animation.
- *
- * @param container WindowContainerToken who's children should defer config notification.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction deferConfigToTransitionEnd(
- @NonNull WindowContainerToken container) {
- final Change change = getOrCreateChange(container.asBinder());
- change.mConfigAtTransitionEnd = true;
- return this;
- }
-
- /**
- * Sets the task as trimmable or not. This can be used to prevent the task from being trimmed by
- * recents. This attribute is set to true on task creation by default.
- *
- * @param isTrimmableFromRecents When {@code true}, task is set as trimmable from recents.
- * @hide
- */
- @NonNull
- public WindowContainerTransaction setTaskTrimmableFromRecents(
- @NonNull WindowContainerToken container,
- boolean isTrimmableFromRecents) {
- mHierarchyOps.add(
- HierarchyOp.createForSetTaskTrimmableFromRecents(container.asBinder(),
- isTrimmableFromRecents));
- return this;
- }
-
- /**
* Merges another WCT into this one.
* @param transfer When true, this will transfer everything from other potentially leaving
* other in an unusable state. When false, other is left alone, but
@@ -1206,7 +1224,7 @@ public final class WindowContainerTransaction implements Parcelable {
@NonNull
public static final Creator<WindowContainerTransaction> CREATOR =
- new Creator<WindowContainerTransaction>() {
+ new Creator<>() {
@Override
public WindowContainerTransaction createFromParcel(@NonNull Parcel in) {
return new WindowContainerTransaction(in);
@@ -1227,19 +1245,17 @@ public final class WindowContainerTransaction implements Parcelable {
public static final int CHANGE_BOUNDS_TRANSACTION = 1 << 1;
public static final int CHANGE_PIP_CALLBACK = 1 << 2;
public static final int CHANGE_HIDDEN = 1 << 3;
- public static final int CHANGE_BOUNDS_TRANSACTION_RECT = 1 << 4;
- public static final int CHANGE_IGNORE_ORIENTATION_REQUEST = 1 << 5;
- public static final int CHANGE_FORCE_NO_PIP = 1 << 6;
- public static final int CHANGE_FORCE_TRANSLUCENT = 1 << 7;
- public static final int CHANGE_DRAG_RESIZING = 1 << 8;
- public static final int CHANGE_RELATIVE_BOUNDS = 1 << 9;
+ public static final int CHANGE_IGNORE_ORIENTATION_REQUEST = 1 << 4;
+ public static final int CHANGE_FORCE_NO_PIP = 1 << 5;
+ public static final int CHANGE_FORCE_TRANSLUCENT = 1 << 6;
+ public static final int CHANGE_DRAG_RESIZING = 1 << 7;
+ public static final int CHANGE_RELATIVE_BOUNDS = 1 << 8;
@IntDef(flag = true, prefix = { "CHANGE_" }, value = {
CHANGE_FOCUSABLE,
CHANGE_BOUNDS_TRANSACTION,
CHANGE_PIP_CALLBACK,
CHANGE_HIDDEN,
- CHANGE_BOUNDS_TRANSACTION_RECT,
CHANGE_IGNORE_ORIENTATION_REQUEST,
CHANGE_FORCE_NO_PIP,
CHANGE_FORCE_TRANSLUCENT,
@@ -1262,7 +1278,6 @@ public final class WindowContainerTransaction implements Parcelable {
private Rect mPinnedBounds = null;
private SurfaceControl.Transaction mBoundsChangeTransaction = null;
- private Rect mBoundsChangeSurfaceBounds = null;
@Nullable
private Rect mRelativeBounds = null;
private boolean mConfigAtTransitionEnd = false;
@@ -1290,10 +1305,6 @@ public final class WindowContainerTransaction implements Parcelable {
mBoundsChangeTransaction =
SurfaceControl.Transaction.CREATOR.createFromParcel(in);
}
- if ((mChangeMask & Change.CHANGE_BOUNDS_TRANSACTION_RECT) != 0) {
- mBoundsChangeSurfaceBounds = new Rect();
- mBoundsChangeSurfaceBounds.readFromParcel(in);
- }
if ((mChangeMask & Change.CHANGE_RELATIVE_BOUNDS) != 0) {
mRelativeBounds = new Rect();
mRelativeBounds.readFromParcel(in);
@@ -1342,10 +1353,6 @@ public final class WindowContainerTransaction implements Parcelable {
if (other.mWindowingMode >= WINDOWING_MODE_UNDEFINED) {
mWindowingMode = other.mWindowingMode;
}
- if (other.mBoundsChangeSurfaceBounds != null) {
- mBoundsChangeSurfaceBounds = transfer ? other.mBoundsChangeSurfaceBounds
- : new Rect(other.mBoundsChangeSurfaceBounds);
- }
if (other.mRelativeBounds != null) {
mRelativeBounds = transfer
? other.mRelativeBounds
@@ -1446,11 +1453,6 @@ public final class WindowContainerTransaction implements Parcelable {
}
@Nullable
- public Rect getBoundsChangeSurfaceBounds() {
- return mBoundsChangeSurfaceBounds;
- }
-
- @Nullable
public Rect getRelativeBounds() {
return mRelativeBounds;
}
@@ -1529,9 +1531,6 @@ public final class WindowContainerTransaction implements Parcelable {
if (mBoundsChangeTransaction != null) {
mBoundsChangeTransaction.writeToParcel(dest, flags);
}
- if (mBoundsChangeSurfaceBounds != null) {
- mBoundsChangeSurfaceBounds.writeToParcel(dest, flags);
- }
if (mRelativeBounds != null) {
mRelativeBounds.writeToParcel(dest, flags);
}
diff --git a/core/java/android/window/flags/device_state_auto_rotate_setting.aconfig b/core/java/android/window/flags/device_state_auto_rotate_setting.aconfig
new file mode 100644
index 000000000000..bb66989b9946
--- /dev/null
+++ b/core/java/android/window/flags/device_state_auto_rotate_setting.aconfig
@@ -0,0 +1,22 @@
+package: "com.android.window.flags"
+container: "system"
+
+flag {
+ name: "enable_device_state_auto_rotate_setting_logging"
+ namespace: "windowing_frontend"
+ description: "Enable device state auto rotate setting logging"
+ bug: "391147112"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "enable_device_state_auto_rotate_setting_refactor"
+ namespace: "windowing_frontend"
+ description: "Enable refactored device state auto rotate setting logic"
+ bug: "350946537"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} \ No newline at end of file
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index e35c3b80a58b..51d488fdd76b 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -583,3 +583,20 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_start_launch_transition_from_taskbar_bugfix"
+ namespace: "lse_desktop_experience"
+ description: "Enables starting a launch transition directly from the taskbar if desktop tasks are visible."
+ bug: "361366053"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "enable_non_default_display_split"
+ namespace: "lse_desktop_experience"
+ description: "Enables split screen on non default displays"
+ bug: "384999213"
+}
diff --git a/core/java/android/window/flags/responsible_apis.aconfig b/core/java/android/window/flags/responsible_apis.aconfig
index 4b5adfcc2c9b..36219812c002 100644
--- a/core/java/android/window/flags/responsible_apis.aconfig
+++ b/core/java/android/window/flags/responsible_apis.aconfig
@@ -81,3 +81,10 @@ flag {
description: "Strict mode violation triggered by grace period usage"
bug: "384807495"
}
+
+flag {
+ name: "bal_clear_allowlist_duration"
+ namespace: "responsible_apis"
+ description: "Clear the allowlist duration when clearAllowBgActivityStarts is called"
+ bug: "322159724"
+}
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 9d7bedc4d0c3..ea54395471cd 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -599,24 +599,35 @@ public class IntentForwarderActivity extends Activity {
Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
sanitizeIntent(forwardIntent);
- Intent intentToCheck = forwardIntent;
- if (Intent.ACTION_CHOOSER.equals(forwardIntent.getAction())) {
+ if (!canForwardInner(forwardIntent, sourceUserId, targetUserId, packageManager,
+ contentResolver)) {
return null;
}
if (forwardIntent.getSelector() != null) {
- intentToCheck = forwardIntent.getSelector();
+ sanitizeIntent(forwardIntent.getSelector());
+ if (!canForwardInner(forwardIntent.getSelector(), sourceUserId, targetUserId,
+ packageManager, contentResolver)) {
+ return null;
+ }
+ }
+ return forwardIntent;
+ }
+
+ private static boolean canForwardInner(Intent intent, int sourceUserId, int targetUserId,
+ IPackageManager packageManager, ContentResolver contentResolver) {
+ if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
+ return false;
}
- String resolvedType = intentToCheck.resolveTypeIfNeeded(contentResolver);
- sanitizeIntent(intentToCheck);
+ String resolvedType = intent.resolveTypeIfNeeded(contentResolver);
try {
if (packageManager.canForwardTo(
- intentToCheck, resolvedType, sourceUserId, targetUserId)) {
- return forwardIntent;
+ intent, resolvedType, sourceUserId, targetUserId)) {
+ return true;
}
} catch (RemoteException e) {
Slog.e(TAG, "PackageManagerService is dead?");
}
- return null;
+ return false;
}
/**
diff --git a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
index dbbe4b9675d7..0b04477657d3 100644
--- a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
+++ b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
@@ -23,8 +23,10 @@ import android.view.Choreographer;
* Provider of timing pulse that uses SurfaceFlinger Vsync Choreographer for frame callbacks.
*
* @hide
+ * @deprecated See b/222698397 - use vsync IDs instead.
*/
// TODO(b/222698397): remove getSfInstance/this class usage and use vsyncId for transactions
+@Deprecated
public final class SfVsyncFrameCallbackProvider implements AnimationFrameCallbackProvider {
private final Choreographer mChoreographer;
@@ -61,4 +63,4 @@ public final class SfVsyncFrameCallbackProvider implements AnimationFrameCallbac
public void setFrameDelay(long delay) {
Choreographer.setFrameDelay(delay);
}
-} \ No newline at end of file
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index dc440e36ca0d..f49c5f1c2b0f 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -84,7 +84,7 @@ public class BatteryStatsHistory {
private static final String TAG = "BatteryStatsHistory";
// Current on-disk Parcel version. Must be updated when the format of the parcelable changes
- private static final int VERSION = 211;
+ private static final int VERSION = 212;
private static final String HISTORY_DIR = "battery-history";
private static final String FILE_SUFFIX = ".bh";
@@ -211,6 +211,8 @@ public class BatteryStatsHistory {
private final MonotonicClock mMonotonicClock;
// Monotonic time when we started writing to the history buffer
private long mHistoryBufferStartTime;
+ // Monotonic time when the last event was written to the history buffer
+ private long mHistoryMonotonicEndTime;
// Monotonically increasing size of written history
private long mMonotonicHistorySize;
private final ArraySet<PowerStats.Descriptor> mWrittenPowerStatsDescriptors = new ArraySet<>();
@@ -423,13 +425,22 @@ public class BatteryStatsHistory {
return file;
}
- void writeToParcel(Parcel out, boolean useBlobs) {
+ void writeToParcel(Parcel out, boolean useBlobs,
+ long preferredEarliestIncludedTimestampMs) {
Trace.traceBegin(TRACE_TAG_SYSTEM_SERVER, "BatteryStatsHistory.writeToParcel");
lock();
try {
final long start = SystemClock.uptimeMillis();
- out.writeInt(mHistoryFiles.size() - 1);
for (int i = 0; i < mHistoryFiles.size() - 1; i++) {
+ long monotonicEndTime = Long.MAX_VALUE;
+ if (i < mHistoryFiles.size() - 1) {
+ monotonicEndTime = mHistoryFiles.get(i + 1).monotonicTimeMs;
+ }
+
+ if (monotonicEndTime < preferredEarliestIncludedTimestampMs) {
+ continue;
+ }
+
AtomicFile file = mHistoryFiles.get(i).atomicFile;
byte[] raw = new byte[0];
try {
@@ -437,6 +448,8 @@ public class BatteryStatsHistory {
} catch (Exception e) {
Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e);
}
+
+ out.writeBoolean(true);
if (useBlobs) {
out.writeBlob(raw);
} else {
@@ -444,6 +457,7 @@ public class BatteryStatsHistory {
out.writeByteArray(raw);
}
}
+ out.writeBoolean(false);
if (DEBUG) {
Slog.d(TAG,
"writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start));
@@ -634,6 +648,7 @@ public class BatteryStatsHistory {
mWritableHistory = writableHistory;
if (mWritableHistory != null) {
mMutable = false;
+ mHistoryMonotonicEndTime = mWritableHistory.mHistoryMonotonicEndTime;
}
if (historyBuffer != null) {
@@ -937,6 +952,8 @@ public class BatteryStatsHistory {
}
// skip monotonic time field.
p.readLong();
+ // skip monotonic end time field
+ p.readLong();
// skip monotonic size field
p.readLong();
@@ -996,6 +1013,8 @@ public class BatteryStatsHistory {
}
// skip monotonic time field.
out.readLong();
+ // skip monotonic end time field
+ out.readLong();
// skip monotonic size field
out.readLong();
return true;
@@ -1024,6 +1043,7 @@ public class BatteryStatsHistory {
p.setDataPosition(0);
p.readInt(); // Skip the version field
long monotonicTime = p.readLong();
+ p.readLong(); // Skip monotonic end time field
p.readLong(); // Skip monotonic size field
p.setDataPosition(pos);
return monotonicTime;
@@ -1086,7 +1106,10 @@ public class BatteryStatsHistory {
public void writeToParcel(Parcel out) {
synchronized (this) {
writeHistoryBuffer(out);
- writeToParcel(out, false /* useBlobs */);
+ /* useBlobs */
+ if (mHistoryDir != null) {
+ mHistoryDir.writeToParcel(out, false /* useBlobs */, 0);
+ }
}
}
@@ -1096,16 +1119,13 @@ public class BatteryStatsHistory {
*
* @param out the output parcel
*/
- public void writeToBatteryUsageStatsParcel(Parcel out) {
+ public void writeToBatteryUsageStatsParcel(Parcel out, long preferredHistoryDurationMs) {
synchronized (this) {
out.writeBlob(mHistoryBuffer.marshall());
- writeToParcel(out, true /* useBlobs */);
- }
- }
-
- private void writeToParcel(Parcel out, boolean useBlobs) {
- if (mHistoryDir != null) {
- mHistoryDir.writeToParcel(out, useBlobs);
+ if (mHistoryDir != null) {
+ mHistoryDir.writeToParcel(out, true /* useBlobs */,
+ mHistoryMonotonicEndTime - preferredHistoryDurationMs);
+ }
}
}
@@ -1166,8 +1186,7 @@ public class BatteryStatsHistory {
private void readFromParcel(Parcel in, boolean useBlobs) {
final long start = SystemClock.uptimeMillis();
mHistoryParcels = new ArrayList<>();
- final int count = in.readInt();
- for (int i = 0; i < count; i++) {
+ while (in.readBoolean()) {
byte[] temp = useBlobs ? in.readBlob() : in.createByteArray();
if (temp == null || temp.length == 0) {
continue;
@@ -2081,6 +2100,8 @@ public class BatteryStatsHistory {
*/
@GuardedBy("this")
private void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
+ mHistoryMonotonicEndTime = cur.time;
+
if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
dest.writeInt(BatteryStatsHistory.DELTA_TIME_ABS);
cur.writeToParcel(dest, 0);
@@ -2396,6 +2417,7 @@ public class BatteryStatsHistory {
}
mHistoryBufferStartTime = in.readLong();
+ mHistoryMonotonicEndTime = in.readLong();
mMonotonicHistorySize = in.readLong();
mHistoryBuffer.setDataSize(0);
@@ -2424,6 +2446,7 @@ public class BatteryStatsHistory {
private void writeHistoryBuffer(Parcel out) {
out.writeInt(BatteryStatsHistory.VERSION);
out.writeLong(mHistoryBufferStartTime);
+ out.writeLong(mHistoryMonotonicEndTime);
out.writeLong(mMonotonicHistorySize);
out.writeInt(mHistoryBuffer.dataSize());
if (DEBUG) {
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 1fa1e0bbc69a..63d031cb581b 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -244,10 +244,4 @@ interface IStatusBarService
/** Shows rear display educational dialog */
void showRearDisplayDialog(int currentBaseState);
-
- /** Unbundle a categorized notification */
- void unbundleNotification(String key);
-
- /** Rebundle an (un)categorized notification */
- void rebundleNotification(String key);
}
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index b3ab5d3cd258..04ce9bcd7afd 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -105,6 +105,7 @@ public class ConversationLayout extends FrameLayout
private ArrayList<MessagingGroup> mAddedGroups = new ArrayList<>();
private Person mUser;
private CharSequence mNameReplacement;
+ private CharSequence mSummarizedContent;
private boolean mIsCollapsed;
private ImageResolver mImageResolver;
private CachingIconView mConversationIconView;
@@ -397,7 +398,7 @@ public class ConversationLayout extends FrameLayout
*
* @param isCollapsed is it collapsed
*/
- @RemotableViewMethod
+ @RemotableViewMethod(asyncImpl = "setIsCollapsedAsync")
public void setIsCollapsed(boolean isCollapsed) {
mIsCollapsed = isCollapsed;
mMessagingLinearLayout.setMaxDisplayedLines(isCollapsed ? 1 : Integer.MAX_VALUE);
@@ -406,6 +407,15 @@ public class ConversationLayout extends FrameLayout
}
/**
+ * setDataAsync needs to do different stuff for the collapsed vs expanded view, so store the
+ * collapsed state early.
+ */
+ public Runnable setIsCollapsedAsync(boolean isCollapsed) {
+ mIsCollapsed = isCollapsed;
+ return () -> setIsCollapsed(isCollapsed);
+ }
+
+ /**
* Set conversation data
*
* @param extras Bundle contains conversation data
@@ -439,8 +449,16 @@ public class ConversationLayout extends FrameLayout
extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
int unreadCount = extras.getInt(Notification.EXTRA_CONVERSATION_UNREAD_MESSAGE_COUNT);
- final List<MessagingMessage> newMessagingMessages =
- createMessages(newMessages, /* isHistoric= */false, usePrecomputedText);
+ List<MessagingMessage> newMessagingMessages;
+ mSummarizedContent = extras.getCharSequence(Notification.EXTRA_SUMMARIZED_CONTENT);
+ if (mSummarizedContent != null && mIsCollapsed) {
+ Notification.MessagingStyle.Message summary =
+ new Notification.MessagingStyle.Message(mSummarizedContent, 0, "");
+ newMessagingMessages = createMessages(List.of(summary), false, usePrecomputedText);
+ } else {
+ newMessagingMessages =
+ createMessages(newMessages, /* isHistoric= */false, usePrecomputedText);
+ }
final List<MessagingMessage> newHistoricMessagingMessages =
createMessages(newHistoricMessages, /* isHistoric= */true, usePrecomputedText);
@@ -463,7 +481,7 @@ public class ConversationLayout extends FrameLayout
return new MessagingData(user, showSpinner, unreadCount,
newHistoricMessagingMessages, newMessagingMessages, groups, senders,
- conversationHeaderData);
+ conversationHeaderData, mSummarizedContent);
}
/**
@@ -1622,6 +1640,9 @@ public class ConversationLayout extends FrameLayout
@Nullable
public CharSequence getConversationText() {
+ if (mSummarizedContent != null) {
+ return mSummarizedContent;
+ }
if (mMessages.isEmpty()) {
return null;
}
diff --git a/core/java/com/android/internal/widget/MessagingData.java b/core/java/com/android/internal/widget/MessagingData.java
index fb1f28fb8ef3..cb5041efd10f 100644
--- a/core/java/com/android/internal/widget/MessagingData.java
+++ b/core/java/com/android/internal/widget/MessagingData.java
@@ -32,6 +32,7 @@ final class MessagingData {
private final List<List<MessagingMessage>> mGroups;
private final List<Person> mSenders;
private final int mUnreadCount;
+ private final CharSequence mSummarization;
private ConversationHeaderData mConversationHeaderData;
@@ -41,8 +42,7 @@ final class MessagingData {
List<Person> senders) {
this(user, showSpinner, /* unreadCount= */0,
historicMessagingMessages, newMessagingMessages,
- groups,
- senders, null);
+ groups, senders, null, null);
}
MessagingData(Person user, boolean showSpinner,
@@ -51,7 +51,8 @@ final class MessagingData {
List<MessagingMessage> newMessagingMessages,
List<List<MessagingMessage>> groups,
List<Person> senders,
- @Nullable ConversationHeaderData conversationHeaderData) {
+ @Nullable ConversationHeaderData conversationHeaderData,
+ CharSequence summarization) {
mUser = user;
mShowSpinner = showSpinner;
mUnreadCount = unreadCount;
@@ -60,6 +61,7 @@ final class MessagingData {
mGroups = groups;
mSenders = senders;
mConversationHeaderData = conversationHeaderData;
+ mSummarization = summarization;
}
public Person getUser() {
@@ -94,4 +96,9 @@ final class MessagingData {
public ConversationHeaderData getConversationHeaderData() {
return mConversationHeaderData;
}
+
+ @Nullable
+ public CharSequence getSummarization() {
+ return mSummarization;
+ }
}
diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java
index a59ee77cc693..c7f22836dd93 100644
--- a/core/java/com/android/internal/widget/MessagingMessage.java
+++ b/core/java/com/android/internal/widget/MessagingMessage.java
@@ -24,7 +24,7 @@ import java.util.ArrayList;
import java.util.Objects;
/**
- * A message of a {@link MessagingLayout}.
+ * A message or summary of a {@link MessagingLayout}.
*/
public interface MessagingMessage extends MessagingLinearLayout.MessagingChild {
diff --git a/core/java/com/android/internal/widget/NotificationProgressBar.java b/core/java/com/android/internal/widget/NotificationProgressBar.java
index 973fd7ecf38b..5e82772730b7 100644
--- a/core/java/com/android/internal/widget/NotificationProgressBar.java
+++ b/core/java/com/android/internal/widget/NotificationProgressBar.java
@@ -830,12 +830,12 @@ public final class NotificationProgressBar extends ProgressBar implements
}
/**
- * Get a color with an opacity that's 40% of the input color.
+ * Get a color with an opacity that's 50% of the input color.
*/
@ColorInt
static int getFadedColor(@ColorInt int color) {
return Color.argb(
- (int) (Color.alpha(color) * 0.4f + 0.5f),
+ (int) (Color.alpha(color) * 0.5f + 0.5f),
Color.red(color),
Color.green(color),
Color.blue(color));
@@ -1193,7 +1193,7 @@ public final class NotificationProgressBar extends ProgressBar implements
* <p>
* <pre>
* When mFaded is set to true, a combination of the following is done to the segment:
- * 1. The drawing color is mColor with opacity updated to 40%.
+ * 1. The drawing color is mColor with opacity updated to 50%.
* 2. The gap between faded and non-faded segments is:
* - the segment-segment gap, when there is no tracker icon
* - 0, when there is tracker icon
diff --git a/core/java/com/android/internal/widget/NotificationProgressDrawable.java b/core/java/com/android/internal/widget/NotificationProgressDrawable.java
index 4ece81c24edc..30dcc67d9ce5 100644
--- a/core/java/com/android/internal/widget/NotificationProgressDrawable.java
+++ b/core/java/com/android/internal/widget/NotificationProgressDrawable.java
@@ -132,6 +132,8 @@ public final class NotificationProgressDrawable extends Drawable {
final float centerY = (float) getBounds().centerY();
final int numParts = mParts.size();
+ final float pointTop = Math.round(centerY - pointRadius);
+ final float pointBottom = Math.round(centerY + pointRadius);
for (int iPart = 0; iPart < numParts; iPart++) {
final DrawablePart part = mParts.get(iPart);
final float start = left + part.mStart;
@@ -146,12 +148,13 @@ public final class NotificationProgressDrawable extends Drawable {
mFillPaint.setColor(segment.mColor);
- mSegRectF.set(start, centerY - radiusY, end, centerY + radiusY);
+ mSegRectF.set(Math.round(start), Math.round(centerY - radiusY), Math.round(end),
+ Math.round(centerY + radiusY));
canvas.drawRoundRect(mSegRectF, cornerRadius, cornerRadius, mFillPaint);
} else if (part instanceof DrawablePoint point) {
// TODO: b/367804171 - actually use a vector asset for the default point
// rather than drawing it as a box?
- mPointRectF.set(start, centerY - pointRadius, end, centerY + pointRadius);
+ mPointRectF.set(Math.round(start), pointTop, Math.round(end), pointBottom);
final float inset = mState.mPointRectInset;
final float cornerRadius = mState.mPointRectCornerRadius;
mPointRectF.inset(inset, inset);
diff --git a/core/java/com/android/internal/widget/remotecompose/accessibility/CoreDocumentAccessibility.java b/core/java/com/android/internal/widget/remotecompose/accessibility/CoreDocumentAccessibility.java
index 2cd4f0362306..52d51539867d 100644
--- a/core/java/com/android/internal/widget/remotecompose/accessibility/CoreDocumentAccessibility.java
+++ b/core/java/com/android/internal/widget/remotecompose/accessibility/CoreDocumentAccessibility.java
@@ -21,6 +21,7 @@ import android.os.Bundle;
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponent;
@@ -45,9 +46,11 @@ import java.util.stream.Stream;
*/
public class CoreDocumentAccessibility implements RemoteComposeDocumentAccessibility {
private final CoreDocument mDocument;
+ private final RemoteContext mRemoteContext;
- public CoreDocumentAccessibility(CoreDocument document) {
+ public CoreDocumentAccessibility(CoreDocument document, RemoteContext remoteContext) {
this.mDocument = document;
+ this.mRemoteContext = remoteContext;
}
@Nullable
@@ -95,7 +98,7 @@ public class CoreDocumentAccessibility implements RemoteComposeDocumentAccessibi
@Override
public boolean performAction(Component component, int action, Bundle arguments) {
if (action == ACTION_CLICK) {
- mDocument.performClick(component.getComponentId());
+ mDocument.performClick(mRemoteContext, component.getComponentId());
return true;
} else {
return false;
diff --git a/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeAccessibilityRegistrar.java b/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeAccessibilityRegistrar.java
index 010253e9cb95..975383ee36b4 100644
--- a/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeAccessibilityRegistrar.java
+++ b/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeAccessibilityRegistrar.java
@@ -19,6 +19,7 @@ import android.annotation.NonNull;
import android.view.View;
import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.RemoteContextAware;
/**
* Trivial wrapper for calling setAccessibilityDelegate on a View. This exists primarily because the
@@ -31,7 +32,8 @@ public class PlatformRemoteComposeAccessibilityRegistrar
View player, @NonNull CoreDocument coreDocument) {
return new PlatformRemoteComposeTouchHelper(
player,
- new CoreDocumentAccessibility(coreDocument),
+ new CoreDocumentAccessibility(
+ coreDocument, ((RemoteContextAware) player).getRemoteContext()),
new AndroidPlatformSemanticNodeApplier());
}
diff --git a/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java b/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java
index 43118a0800fb..c8474b19058f 100644
--- a/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java
+++ b/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java
@@ -28,6 +28,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.widget.ExploreByTouchHelper;
import com.android.internal.widget.remotecompose.core.CoreDocument;
+import com.android.internal.widget.remotecompose.core.RemoteContextAware;
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.semantics.AccessibilitySemantics;
import com.android.internal.widget.remotecompose.core.semantics.AccessibleComponent.Mode;
@@ -55,7 +56,8 @@ public class PlatformRemoteComposeTouchHelper extends ExploreByTouchHelper {
View player, @NonNull CoreDocument coreDocument) {
return new PlatformRemoteComposeTouchHelper(
player,
- new CoreDocumentAccessibility(coreDocument),
+ new CoreDocumentAccessibility(
+ coreDocument, ((RemoteContextAware) player).getRemoteContext()),
new AndroidPlatformSemanticNodeApplier());
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
index f5f4e4332d28..0cfaf5592d6f 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
@@ -62,7 +62,7 @@ public class CoreDocument {
// We also keep a more fine-grained BUILD number, exposed as
// ID_API_LEVEL = DOCUMENT_API_LEVEL + BUILD
- static final float BUILD = 0.3f;
+ static final float BUILD = 0.4f;
@NonNull ArrayList<Operation> mOperations = new ArrayList<>();
@@ -860,16 +860,22 @@ public class CoreDocument {
*
* @param id the click area id
*/
- public void performClick(int id) {
+ public void performClick(@NonNull RemoteContext context, int id) {
for (ClickAreaRepresentation clickArea : mClickAreas) {
if (clickArea.mId == id) {
warnClickListeners(clickArea);
return;
}
}
+
for (IdActionCallback listener : mIdActionListeners) {
listener.onAction(id, "");
}
+
+ Component component = getComponent(id);
+ if (component != null) {
+ component.onClick(context, this, -1, -1);
+ }
}
/** Warn click listeners when a click area is activated */
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
index 0b6a3c415e4a..3760af2f7460 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
@@ -18,6 +18,7 @@ package com.android.internal.widget.remotecompose.core;
import android.annotation.NonNull;
import com.android.internal.widget.remotecompose.core.operations.BitmapData;
+import com.android.internal.widget.remotecompose.core.operations.BitmapFontData;
import com.android.internal.widget.remotecompose.core.operations.ClickArea;
import com.android.internal.widget.remotecompose.core.operations.ClipPath;
import com.android.internal.widget.remotecompose.core.operations.ClipRect;
@@ -30,6 +31,7 @@ import com.android.internal.widget.remotecompose.core.operations.DataMapIds;
import com.android.internal.widget.remotecompose.core.operations.DataMapLookup;
import com.android.internal.widget.remotecompose.core.operations.DrawArc;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmap;
+import com.android.internal.widget.remotecompose.core.operations.DrawBitmapFontText;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmapInt;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmapScaled;
import com.android.internal.widget.remotecompose.core.operations.DrawCircle;
@@ -45,6 +47,8 @@ import com.android.internal.widget.remotecompose.core.operations.DrawTextOnPath;
import com.android.internal.widget.remotecompose.core.operations.DrawTweenPath;
import com.android.internal.widget.remotecompose.core.operations.FloatConstant;
import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
+import com.android.internal.widget.remotecompose.core.operations.FloatFunctionCall;
+import com.android.internal.widget.remotecompose.core.operations.FloatFunctionDefine;
import com.android.internal.widget.remotecompose.core.operations.Header;
import com.android.internal.widget.remotecompose.core.operations.IntegerExpression;
import com.android.internal.widget.remotecompose.core.operations.MatrixRestore;
@@ -147,12 +151,14 @@ public class Operations {
public static final int DATA_BITMAP = 101;
public static final int DATA_SHADER = 45;
public static final int DATA_TEXT = 102;
+ public static final int DATA_BITMAP_FONT = 167;
///////////////////////////// =====================
public static final int CLIP_PATH = 38;
public static final int CLIP_RECT = 39;
public static final int PAINT_VALUES = 40;
public static final int DRAW_RECT = 42;
+ public static final int DRAW_BITMAP_FONT_TEXT_RUN = 48;
public static final int DRAW_TEXT_RUN = 43;
public static final int DRAW_CIRCLE = 46;
public static final int DRAW_LINE = 47;
@@ -196,11 +202,13 @@ public class Operations {
public static final int PATH_TWEEN = 158;
public static final int PATH_CREATE = 159;
public static final int PATH_ADD = 160;
- public static final int PARTICLE_CREATE = 161;
+ public static final int PARTICLE_DEFINE = 161;
public static final int PARTICLE_PROCESS = 162;
public static final int PARTICLE_LOOP = 163;
public static final int IMPULSE_START = 164;
public static final int IMPULSE_PROCESS = 165;
+ public static final int FUNCTION_CALL = 166;
+ public static final int FUNCTION_DEFINE = 168;
///////////////////////////////////////// ======================
@@ -276,6 +284,7 @@ public class Operations {
map.put(HEADER, Header::read);
map.put(DRAW_BITMAP_INT, DrawBitmapInt::read);
map.put(DATA_BITMAP, BitmapData::read);
+ map.put(DATA_BITMAP_FONT, BitmapFontData::read);
map.put(DATA_TEXT, TextData::read);
map.put(THEME, Theme::read);
map.put(CLICK_AREA, ClickArea::read);
@@ -292,6 +301,7 @@ public class Operations {
map.put(DRAW_ROUND_RECT, DrawRoundRect::read);
map.put(DRAW_TEXT_ON_PATH, DrawTextOnPath::read);
map.put(DRAW_TEXT_RUN, DrawText::read);
+ map.put(DRAW_BITMAP_FONT_TEXT_RUN, DrawBitmapFontText::read);
map.put(DRAW_TWEEN_PATH, DrawTweenPath::read);
map.put(DATA_PATH, PathData::read);
map.put(PAINT_VALUES, PaintData::read);
@@ -389,8 +399,10 @@ public class Operations {
map.put(PATH_ADD, PathAppend::read);
map.put(IMPULSE_START, ImpulseOperation::read);
map.put(IMPULSE_PROCESS, ImpulseProcess::read);
- map.put(PARTICLE_CREATE, ParticlesCreate::read);
+ map.put(PARTICLE_DEFINE, ParticlesCreate::read);
map.put(PARTICLE_LOOP, ParticlesLoop::read);
+ map.put(FUNCTION_CALL, FloatFunctionCall::read);
+ map.put(FUNCTION_DEFINE, FloatFunctionDefine::read);
map.put(ACCESSIBILITY_SEMANTICS, CoreSemantics::read);
// map.put(ACCESSIBILITY_CUSTOM_ACTION, CoreSemantics::read);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
index 1cb8fefde80c..f83ecef1074d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.internal.widget.remotecompose.core.operations.BitmapData;
+import com.android.internal.widget.remotecompose.core.operations.BitmapFontData;
import com.android.internal.widget.remotecompose.core.operations.ClickArea;
import com.android.internal.widget.remotecompose.core.operations.ClipPath;
import com.android.internal.widget.remotecompose.core.operations.ClipRect;
@@ -33,6 +34,7 @@ import com.android.internal.widget.remotecompose.core.operations.DataMapIds;
import com.android.internal.widget.remotecompose.core.operations.DataMapLookup;
import com.android.internal.widget.remotecompose.core.operations.DrawArc;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmap;
+import com.android.internal.widget.remotecompose.core.operations.DrawBitmapFontText;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmapInt;
import com.android.internal.widget.remotecompose.core.operations.DrawBitmapScaled;
import com.android.internal.widget.remotecompose.core.operations.DrawCircle;
@@ -48,6 +50,8 @@ import com.android.internal.widget.remotecompose.core.operations.DrawTextOnPath;
import com.android.internal.widget.remotecompose.core.operations.DrawTweenPath;
import com.android.internal.widget.remotecompose.core.operations.FloatConstant;
import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
+import com.android.internal.widget.remotecompose.core.operations.FloatFunctionCall;
+import com.android.internal.widget.remotecompose.core.operations.FloatFunctionDefine;
import com.android.internal.widget.remotecompose.core.operations.Header;
import com.android.internal.widget.remotecompose.core.operations.IntegerExpression;
import com.android.internal.widget.remotecompose.core.operations.MatrixRestore;
@@ -557,6 +561,18 @@ public class RemoteComposeBuffer {
}
/**
+ * Records a bitmap font and returns an ID.
+ *
+ * @param glyphs The glyphs that define the bitmap font
+ * @return id of the BitmapFont
+ */
+ public int addBitmapFont(BitmapFontData.Glyph[] glyphs) {
+ int id = mRemoteComposeState.nextId();
+ BitmapFontData.apply(mBuffer, id, glyphs);
+ return id;
+ }
+
+ /**
* This defines the name of the bitmap given the id.
*
* @param id of the Bitmap
@@ -825,6 +841,22 @@ public class RemoteComposeBuffer {
}
/**
+ * Draw the text with a bitmap font, with origin at (x,y). The origin is interpreted based on
+ * the Align setting in the paint.
+ *
+ * @param textId The text to be drawn
+ * @param bitmapFontId The id of the bitmap font to draw with
+ * @param start The index of the first character in text to draw
+ * @param end (end - 1) is the index of the last character in text to draw
+ * @param x The x-coordinate of the origin of the text being drawn
+ * @param y The y-coordinate of the baseline of the text being drawn
+ */
+ public void addDrawBitmapFontTextRun(
+ int textId, int bitmapFontId, int start, int end, float x, float y) {
+ DrawBitmapFontText.apply(mBuffer, textId, bitmapFontId, start, end, x, y);
+ }
+
+ /**
* Draw a text on canvas at relative to position (x, y), offset panX and panY. <br>
* The panning factors (panX, panY) mapped to the resulting bounding box of the text, in such a
* way that a panning factor of (0.0, 0.0) would center the text at (x, y)
@@ -1060,6 +1092,14 @@ public class RemoteComposeBuffer {
return "v1.0";
}
+ /**
+ * Initialize a buffer from a file
+ *
+ * @param path the file path
+ * @param remoteComposeState the associated state
+ * @return the RemoteComposeBuffer
+ * @throws IOException
+ */
@NonNull
public static RemoteComposeBuffer fromFile(
@NonNull String path, @NonNull RemoteComposeState remoteComposeState)
@@ -1134,11 +1174,24 @@ public class RemoteComposeBuffer {
}
}
+ /**
+ * Read the content of the file into the buffer
+ *
+ * @param file a target file
+ * @param buffer a RemoteComposeBuffer
+ * @throws IOException
+ */
static void read(@NonNull File file, @NonNull RemoteComposeBuffer buffer) throws IOException {
FileInputStream fd = new FileInputStream(file);
read(fd, buffer);
}
+ /**
+ * Initialize a buffer from an input stream
+ *
+ * @param fd the input stream
+ * @param buffer a RemoteComposeBuffer
+ */
public static void read(@NonNull InputStream fd, @NonNull RemoteComposeBuffer buffer) {
try {
byte[] bytes = readAllBytes(fd);
@@ -1150,6 +1203,13 @@ public class RemoteComposeBuffer {
}
}
+ /**
+ * Load a byte buffer from the input stream
+ *
+ * @param is the input stream
+ * @return a byte buffer containing the input stream content
+ * @throws IOException
+ */
private static byte[] readAllBytes(@NonNull InputStream is) throws IOException {
byte[] buff = new byte[32 * 1024]; // moderate size buff to start
int red = 0;
@@ -1684,7 +1744,27 @@ public class RemoteComposeBuffer {
* @return id of the color (color ids are short)
*/
public short addColorExpression(int alpha, float hue, float sat, float value) {
- ColorExpression c = new ColorExpression(0, alpha, hue, sat, value);
+ ColorExpression c =
+ new ColorExpression(0, ColorExpression.HSV_MODE, alpha, hue, sat, value);
+ short id = (short) mRemoteComposeState.cacheData(c);
+ c.mId = id;
+ c.write(mBuffer);
+ return id;
+ }
+
+ /**
+ * Color calculated by Alpha, Red, Green and Blue. (as floats they can be variables used to
+ * create color transitions)
+ *
+ * @param alpha the alpha value of the color
+ * @param red the red component of the color
+ * @param green the green component of the color
+ * @param blue the blue component of the color
+ * @return id of the color (color ids are short)
+ */
+ public short addColorExpression(float alpha, float red, float green, float blue) {
+ ColorExpression c =
+ new ColorExpression(0, ColorExpression.ARGB_MODE, alpha, red, green, blue);
short id = (short) mRemoteComposeState.cacheData(c);
c.mId = id;
c.write(mBuffer);
@@ -2179,10 +2259,21 @@ public class RemoteComposeBuffer {
textAlign);
}
+ /**
+ * Returns the next available id for the given type
+ *
+ * @param type the type of the value
+ * @return a unique id
+ */
public int createID(int type) {
return mRemoteComposeState.nextId(type);
}
+ /**
+ * Returns the next available id
+ *
+ * @return a unique id
+ */
public int nextId() {
return mRemoteComposeState.nextId();
}
@@ -2243,4 +2334,27 @@ public class RemoteComposeBuffer {
public void addParticleLoopEnd() {
ContainerEnd.apply(mBuffer);
}
+
+ /**
+ * @param fid The id of the function
+ * @param args The arguments of the function
+ */
+ public void defineFloatFunction(int fid, int[] args) {
+ FloatFunctionDefine.apply(mBuffer, fid, args);
+ }
+
+ /** end the definition of the function */
+ public void addEndFloatFunctionDef() {
+ ContainerEnd.apply(mBuffer);
+ }
+
+ /**
+ * add a function call
+ *
+ * @param id the id of the function to call
+ * @param args the arguments of the function
+ */
+ public void callFloatFunction(int id, float[] args) {
+ FloatFunctionCall.apply(mBuffer, id, args);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContextAware.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContextAware.java
new file mode 100644
index 000000000000..bf9a8c02d525
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContextAware.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core;
+
+/**
+ * This interface defines a contract for objects that are aware of a {@link RemoteContext}.
+ *
+ * <p>PlayerViews should implement to provide access to the RemoteContext.
+ */
+public interface RemoteContextAware {
+
+ /**
+ * Returns the remote context
+ *
+ * @return a RemoteContext
+ */
+ RemoteContext getRemoteContext();
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java
new file mode 100644
index 000000000000..cbd30dc21caf
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapFontData.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core.operations;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT_ARRAY;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** Operation to deal with bitmap font data. */
+public class BitmapFontData extends Operation {
+ private static final int OP_CODE = Operations.DATA_BITMAP_FONT;
+ private static final String CLASS_NAME = "BitmapFontData";
+
+ int mId;
+
+ // Sorted in order of decreasing mChars length.
+ @NonNull Glyph[] mFontGlyphs;
+
+ /**
+ * A bitmap font is comprised of a collection of Glyphs. Note each Glyph has its own bitmap
+ * rather than using a texture atlas.
+ */
+ public static class Glyph {
+ /** The character(s) this glyph represents. */
+ public String mChars;
+
+ /** The id of the bitmap for this glyph, or -1 for space. */
+ public int mBitmapId;
+
+ /** The margin in pixels to the left of the glyph bitmap. */
+ public short mMarginLeft;
+
+ /** The margin in pixels above of the glyph bitmap. */
+ public short mMarginTop;
+
+ /** The margin in pixels to the right of the glyph bitmap. */
+ public short mMarginRight;
+
+ /** The margin in pixels below the glyph bitmap. */
+ public short mMarginBottom;
+
+ public short mBitmapWidth;
+ public short mBitmapHeight;
+
+ public Glyph() {}
+
+ public Glyph(
+ String chars,
+ int bitmapId,
+ short marginLeft,
+ short marginTop,
+ short marginRight,
+ short marginBottom,
+ short width,
+ short height) {
+ mChars = chars;
+ mBitmapId = bitmapId;
+ mMarginLeft = marginLeft;
+ mMarginTop = marginTop;
+ mMarginRight = marginRight;
+ mMarginBottom = marginBottom;
+ mBitmapWidth = width;
+ mBitmapHeight = height;
+ }
+ }
+
+ /**
+ * create a bitmap font structure.
+ *
+ * @param id the id of the bitmap font
+ * @param fontGlyphs the glyphs that define the bitmap font
+ */
+ public BitmapFontData(int id, @NonNull Glyph[] fontGlyphs) {
+ mId = id;
+ mFontGlyphs = fontGlyphs;
+
+ // Sort in order of decreasing mChars length.
+ Arrays.sort(mFontGlyphs, (o1, o2) -> o2.mChars.length() - o1.mChars.length());
+ }
+
+ @Override
+ public void write(@NonNull WireBuffer buffer) {
+ apply(buffer, mId, mFontGlyphs);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "BITMAP FONT DATA " + mId;
+ }
+
+ /**
+ * The name of the class
+ *
+ * @return the name
+ */
+ @NonNull
+ public static String name() {
+ return CLASS_NAME;
+ }
+
+ /**
+ * The OP_CODE for this command
+ *
+ * @return the opcode
+ */
+ public static int id() {
+ return OP_CODE;
+ }
+
+ /**
+ * Add the image to the document
+ *
+ * @param buffer document to write to
+ * @param id the id the bitmap font will be stored under
+ * @param glyphs glyph metadata
+ */
+ public static void apply(@NonNull WireBuffer buffer, int id, @NonNull Glyph[] glyphs) {
+ buffer.start(OP_CODE);
+ buffer.writeInt(id);
+ buffer.writeInt(glyphs.length);
+ for (Glyph element : glyphs) {
+ buffer.writeUTF8(element.mChars);
+ buffer.writeInt(element.mBitmapId);
+ buffer.writeShort(element.mMarginLeft);
+ buffer.writeShort(element.mMarginTop);
+ buffer.writeShort(element.mMarginRight);
+ buffer.writeShort(element.mMarginBottom);
+ buffer.writeShort(element.mBitmapWidth);
+ buffer.writeShort(element.mBitmapHeight);
+ }
+ }
+
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+ int id = buffer.readInt();
+ int numGlyphElements = buffer.readInt();
+ Glyph[] glyphs = new Glyph[numGlyphElements];
+ for (int i = 0; i < numGlyphElements; i++) {
+ glyphs[i] = new Glyph();
+ glyphs[i].mChars = buffer.readUTF8();
+ glyphs[i].mBitmapId = buffer.readInt();
+ glyphs[i].mMarginLeft = (short) buffer.readShort();
+ glyphs[i].mMarginTop = (short) buffer.readShort();
+ glyphs[i].mMarginRight = (short) buffer.readShort();
+ glyphs[i].mMarginBottom = (short) buffer.readShort();
+ glyphs[i].mBitmapWidth = (short) buffer.readShort();
+ glyphs[i].mBitmapHeight = (short) buffer.readShort();
+ }
+
+ operations.add(new BitmapFontData(id, glyphs));
+ }
+
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
+ public static void documentation(@NonNull DocumentationBuilder doc) {
+ doc.operation("Data Operations", OP_CODE, CLASS_NAME)
+ .description("Bitmap font data")
+ .field(DocumentedOperation.INT, "id", "id of bitmap font data")
+ .field(INT_ARRAY, "glyphNodes", "list used to greedily convert strings into glyphs")
+ .field(INT_ARRAY, "glyphElements", "");
+ }
+
+ @Override
+ public void apply(@NonNull RemoteContext context) {
+ context.putObject(mId, this);
+ }
+
+ @NonNull
+ @Override
+ public String deepToString(@NonNull String indent) {
+ return indent + toString();
+ }
+
+ /** Finds the largest glyph matching the string at the specified offset, or returns null. */
+ @Nullable
+ public Glyph lookupGlyph(String string, int offset) {
+ // Since mFontGlyphs is sorted on decreasing size, it will match the longest items first.
+ // It is expected that the mFontGlyphs array will be fairly small.
+ for (Glyph glyph : mFontGlyphs) {
+ if (string.startsWith(glyph.mChars, offset)) {
+ return glyph;
+ }
+ }
+ return null;
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java
index b385ecd9e5f7..73f99ccb4405 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java
@@ -38,7 +38,13 @@ public class ColorExpression extends Operation implements VariableSupport {
private static final int OP_CODE = Operations.COLOR_EXPRESSIONS;
private static final String CLASS_NAME = "ColorExpression";
public int mId;
+
+ /**
+ * Mode of the color expression 0 = two colors and a tween 1 = color1 is a colorID. 2 color2 is
+ * a colorID. 3 = color1 & color2 are ids 4 = H S V mode 5 = RGB mode 6 = ARGB mode
+ */
int mMode;
+
public int mColor1;
public int mColor2;
public float mTween = 0.0f;
@@ -51,11 +57,49 @@ public class ColorExpression extends Operation implements VariableSupport {
public float mOutValue = 0;
public int mAlpha = 0xFF; // only used in hsv mode
+ private float mArgbAlpha = 0.0f;
+ private float mArgbRed = 0.0f;
+ private float mArgbGreen = 0.0f;
+ private float mArgbBlue = 0.0f;
+
+ private float mOutArgbAlpha = 0.0f;
+ private float mOutArgbRed = 0.0f;
+ private float mOutArgbGreen = 0.0f;
+ private float mOutArgbBlue = 0.0f;
+
public float mOutTween = 0.0f;
public int mOutColor1;
public int mOutColor2;
- public static final int HSV_MODE = 4;
+ /** COLOR_COLOR_INTERPOLATE */
+ public static final byte COLOR_COLOR_INTERPOLATE = 0;
+
+ /** COLOR_ID_INTERPOLATE */
+ public static final byte ID_COLOR_INTERPOLATE = 1;
+
+ /** ID_COLOR_INTERPOLATE */
+ public static final byte COLOR_ID_INTERPOLATE = 2;
+
+ /** ID_ID_INTERPOLATE */
+ public static final byte ID_ID_INTERPOLATE = 3;
+
+ /** H S V mode */
+ public static final byte HSV_MODE = 4;
+
+ /** ARGB mode */
+ public static final byte ARGB_MODE = 5;
+
+ /** ARGB mode with a being an id */
+ public static final byte IDARGB_MODE = 6;
+
+ /**
+ * Create a new ColorExpression object
+ *
+ * @param id the id of the color
+ * @param hue the hue of the color
+ * @param sat the saturation of the color
+ * @param value the value of the color
+ */
public ColorExpression(int id, float hue, float sat, float value) {
mMode = HSV_MODE;
mAlpha = 0xFF;
@@ -67,7 +111,21 @@ public class ColorExpression extends Operation implements VariableSupport {
mTween = value;
}
- public ColorExpression(int id, int alpha, float hue, float sat, float value) {
+ /**
+ * Create a new ColorExpression object based on HSV
+ *
+ * @param id id of the color
+ * @param mode the mode of the color
+ * @param alpha the alpha of the color
+ * @param hue the hue of the color
+ * @param sat the saturation of the color
+ * @param value the value (brightness) of the color
+ */
+ public ColorExpression(int id, byte mode, int alpha, float hue, float sat, float value) {
+ if (mode != HSV_MODE) {
+ throw new RuntimeException("Invalid mode " + mode);
+ }
+ mId = id;
mMode = HSV_MODE;
mAlpha = alpha;
mOutHue = mHue = hue;
@@ -78,6 +136,15 @@ public class ColorExpression extends Operation implements VariableSupport {
mTween = value;
}
+ /**
+ * Create a new ColorExpression object based interpolationg two colors
+ *
+ * @param id the id of the color
+ * @param mode the type of mode (are colors ids or actual values)
+ * @param color1 the first color to use
+ * @param color2 the second color to use
+ * @param tween the value to use to interpolate between the two colors
+ */
public ColorExpression(int id, int mode, int color1, int color2, float tween) {
this.mId = id;
this.mMode = mode & 0xFF;
@@ -95,6 +162,28 @@ public class ColorExpression extends Operation implements VariableSupport {
this.mOutColor2 = color2;
}
+ /**
+ * Create a new ColorExpression object based on ARGB
+ *
+ * @param id the id of the color
+ * @param mode the mode must be ARGB_MODE
+ * @param alpha the alpha value of the color
+ * @param red the red of component the color
+ * @param green the greej component of the color
+ * @param blue the blue of component the color
+ */
+ public ColorExpression(int id, byte mode, float alpha, float red, float green, float blue) {
+ if (mode != ARGB_MODE) {
+ throw new RuntimeException("Invalid mode " + mode);
+ }
+ mMode = ARGB_MODE;
+ mId = id;
+ mOutArgbAlpha = mArgbAlpha = alpha;
+ mOutArgbRed = mArgbRed = red;
+ mOutArgbGreen = mArgbGreen = green;
+ mOutArgbBlue = mArgbBlue = blue;
+ }
+
@Override
public void updateVariables(@NonNull RemoteContext context) {
if (mMode == 4) {
@@ -108,6 +197,20 @@ public class ColorExpression extends Operation implements VariableSupport {
mOutValue = context.getFloat(Utils.idFromNan(mValue));
}
}
+ if (mMode == ARGB_MODE) {
+ if (Float.isNaN(mArgbAlpha)) {
+ mOutArgbAlpha = context.getFloat(Utils.idFromNan(mArgbAlpha));
+ }
+ if (Float.isNaN(mArgbRed)) {
+ mOutArgbRed = context.getFloat(Utils.idFromNan(mArgbRed));
+ }
+ if (Float.isNaN(mArgbGreen)) {
+ mOutArgbGreen = context.getFloat(Utils.idFromNan(mArgbGreen));
+ }
+ if (Float.isNaN(mArgbBlue)) {
+ mOutArgbBlue = context.getFloat(Utils.idFromNan(mArgbBlue));
+ }
+ }
if (Float.isNaN(mTween)) {
mOutTween = context.getFloat(Utils.idFromNan(mTween));
}
@@ -146,13 +249,21 @@ public class ColorExpression extends Operation implements VariableSupport {
@Override
public void apply(@NonNull RemoteContext context) {
- if (mMode == 4) {
+ if (mMode == HSV_MODE) {
context.loadColor(
mId, (mAlpha << 24) | (0xFFFFFF & Utils.hsvToRgb(mOutHue, mOutSat, mOutValue)));
return;
}
+ if (mMode == ARGB_MODE) {
+ context.loadColor(
+ mId, Utils.toARGB(mOutArgbAlpha, mOutArgbRed, mOutArgbGreen, mOutArgbBlue));
+ return;
+ }
if (mOutTween == 0.0) {
- context.loadColor(mId, mColor1);
+ if ((mMode & 1) == 1) {
+ mOutColor1 = context.getColor(mColor1);
+ }
+ context.loadColor(mId, mOutColor1);
} else {
if ((mMode & 1) == 1) {
mOutColor1 = context.getColor(mColor1);
@@ -167,14 +278,36 @@ public class ColorExpression extends Operation implements VariableSupport {
@Override
public void write(@NonNull WireBuffer buffer) {
- int mode = mMode | (mAlpha << 16);
- apply(buffer, mId, mode, mColor1, mColor2, mTween);
+ int mode;
+ switch (mMode) {
+ case ARGB_MODE:
+ apply(buffer, mId, mArgbAlpha, mArgbRed, mArgbGreen, mArgbBlue);
+ break;
+
+ case HSV_MODE:
+ mOutValue = mValue;
+ mColor1 = Float.floatToRawIntBits(mHue);
+ mColor2 = Float.floatToRawIntBits(mSat);
+ mode = mMode | (mAlpha << 16);
+ apply(buffer, mId, mode, mColor1, mColor2, mTween);
+
+ break;
+ case COLOR_ID_INTERPOLATE:
+ case ID_COLOR_INTERPOLATE:
+ case ID_ID_INTERPOLATE:
+ case COLOR_COLOR_INTERPOLATE:
+ apply(buffer, mId, mMode, mColor1, mColor2, mTween);
+
+ break;
+ default:
+ throw new RuntimeException("Invalid mode ");
+ }
}
@NonNull
@Override
public String toString() {
- if (mMode == 4) {
+ if (mMode == HSV_MODE) {
return "ColorExpression["
+ mId
+ "] = hsv ("
@@ -185,7 +318,20 @@ public class ColorExpression extends Operation implements VariableSupport {
+ Utils.floatToString(mValue)
+ ")";
}
-
+ Utils.log(" ColorExpression toString" + mId + " " + mMode);
+ if (mMode == ARGB_MODE) {
+ return "ColorExpression["
+ + mId
+ + "] = rgb ("
+ + Utils.floatToString(mArgbAlpha)
+ + ", "
+ + Utils.floatToString(mArgbRed)
+ + ", "
+ + Utils.floatToString(mArgbGreen)
+ + ", "
+ + Utils.floatToString(mArgbRed)
+ + ")";
+ }
String c1 = (mMode & 1) == 1 ? "[" + mColor1 + "]" : Utils.colorInt(mColor1);
String c2 = (mMode & 2) == 2 ? "[" + mColor2 + "]" : Utils.colorInt(mColor2);
return "ColorExpression["
@@ -230,12 +376,38 @@ public class ColorExpression extends Operation implements VariableSupport {
*/
public static void apply(
@NonNull WireBuffer buffer, int id, int mode, int color1, int color2, float tween) {
+ apply(buffer, id, mode, color1, color2, Float.floatToRawIntBits(tween));
+ }
+
+ /**
+ * Call to write a ColorExpression object on the buffer
+ *
+ * @param buffer
+ * @param id of the ColorExpression object
+ * @param alpha
+ * @param red
+ * @param green
+ * @param blue
+ */
+ public static void apply(
+ @NonNull WireBuffer buffer, int id, float alpha, float red, float green, float blue) {
+ int param1 = (Float.isNaN(alpha)) ? IDARGB_MODE : ARGB_MODE;
+ param1 |=
+ (Float.isNaN(alpha)) ? Utils.idFromNan(alpha) << 16 : ((int) (alpha * 1024)) << 16;
+ int param2 = Float.floatToRawIntBits(red);
+ int param3 = Float.floatToRawIntBits(green);
+ int param4 = Float.floatToRawIntBits(blue);
+ apply(buffer, id, param1, param2, param3, param4);
+ }
+
+ private static void apply(
+ @NonNull WireBuffer buffer, int id, int param1, int param2, int param3, int param4) {
buffer.start(OP_CODE);
buffer.writeInt(id);
- buffer.writeInt(mode);
- buffer.writeInt(color1);
- buffer.writeInt(color2);
- buffer.writeFloat(tween);
+ buffer.writeInt(param1);
+ buffer.writeInt(param2);
+ buffer.writeInt(param3);
+ buffer.writeInt(param4);
}
/**
@@ -246,12 +418,48 @@ public class ColorExpression extends Operation implements VariableSupport {
*/
public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int id = buffer.readInt();
- int mode = buffer.readInt();
- int color1 = buffer.readInt();
- int color2 = buffer.readInt();
- float tween = buffer.readFloat();
-
- operations.add(new ColorExpression(id, mode, color1, color2, tween));
+ int param1 = buffer.readInt();
+ int param2 = buffer.readInt();
+ int param3 = buffer.readInt();
+ int param4 = buffer.readInt();
+ int mode = param1 & 0xFF;
+ float alpha;
+ float red;
+ float green;
+ float blue;
+ switch (mode) {
+ case IDARGB_MODE:
+ alpha = Utils.asNan(param1 >> 16);
+ red = Float.intBitsToFloat(param2);
+ green = Float.intBitsToFloat(param3);
+ blue = Float.intBitsToFloat(param4);
+ operations.add(new ColorExpression(id, (byte) ARGB_MODE, alpha, red, green, blue));
+ break;
+ case ARGB_MODE:
+ alpha = (param1 >> 16) / 1024.0f;
+ red = Float.intBitsToFloat(param2);
+ green = Float.intBitsToFloat(param3);
+ blue = Float.intBitsToFloat(param4);
+ operations.add(new ColorExpression(id, (byte) ARGB_MODE, alpha, red, green, blue));
+ break;
+ case HSV_MODE:
+ alpha = (param1 >> 16) / 1024.0f;
+ float hue = Float.intBitsToFloat(param2);
+ float sat = Float.intBitsToFloat(param3);
+ float value = Float.intBitsToFloat(param4);
+ operations.add(new ColorExpression(id, HSV_MODE, (param1 >> 16), hue, sat, value));
+ break;
+ case COLOR_ID_INTERPOLATE:
+ case ID_COLOR_INTERPOLATE:
+ case ID_ID_INTERPOLATE:
+ case COLOR_COLOR_INTERPOLATE:
+ operations.add(
+ new ColorExpression(
+ id, mode, param2, param3, Float.intBitsToFloat(param4)));
+ break;
+ default:
+ throw new RuntimeException("Invalid mode " + mode);
+ }
}
/**
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java
index 7f1ba6f94065..411353bd3509 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBase2.java
@@ -31,8 +31,8 @@ import java.util.List;
/** Base class for commands that take 3 float */
public abstract class DrawBase2 extends PaintOperation implements VariableSupport {
@NonNull protected String mName = "DrawRectBase";
- protected float mV1;
- protected float mV2;
+ float mV1;
+ float mV2;
float mValue1;
float mValue2;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java
new file mode 100644
index 000000000000..258988e8b00a
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapFontText.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core.operations;
+
+import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString;
+
+import android.annotation.NonNull;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
+
+import java.util.List;
+
+/** Draw Text */
+public class DrawBitmapFontText extends PaintOperation implements VariableSupport {
+ private static final int OP_CODE = Operations.DRAW_BITMAP_FONT_TEXT_RUN;
+ private static final String CLASS_NAME = "DrawBitmapFontText";
+ int mTextID;
+ int mBitmapFontID;
+ int mStart;
+ int mEnd;
+ float mX;
+ float mY;
+ float mOutX;
+ float mOutY;
+
+ public DrawBitmapFontText(int textID, int bitmapFontID, int start, int end, float x, float y) {
+ mTextID = textID;
+ mBitmapFontID = bitmapFontID;
+ mStart = start;
+ mEnd = end;
+ mOutX = mX = x;
+ mOutY = mY = y;
+ }
+
+ @Override
+ public void updateVariables(@NonNull RemoteContext context) {
+ mOutX = Float.isNaN(mX) ? context.getFloat(Utils.idFromNan(mX)) : mX;
+ mOutY = Float.isNaN(mY) ? context.getFloat(Utils.idFromNan(mY)) : mY;
+ }
+
+ @Override
+ public void registerListening(@NonNull RemoteContext context) {
+ if (Float.isNaN(mX)) {
+ context.listensTo(Utils.idFromNan(mX), this);
+ }
+ if (Float.isNaN(mY)) {
+ context.listensTo(Utils.idFromNan(mY), this);
+ }
+ }
+
+ @Override
+ public void write(@NonNull WireBuffer buffer) {
+ apply(buffer, mTextID, mBitmapFontID, mStart, mEnd, mX, mY);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "DrawBitmapFontText ["
+ + mTextID
+ + "] "
+ + mBitmapFontID
+ + ", "
+ + mStart
+ + ", "
+ + mEnd
+ + ", "
+ + floatToString(mX, mOutX)
+ + ", "
+ + floatToString(mY, mOutY);
+ }
+
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+ int text = buffer.readInt();
+ int bitmapFont = buffer.readInt();
+ int start = buffer.readInt();
+ int end = buffer.readInt();
+ float x = buffer.readFloat();
+ float y = buffer.readFloat();
+ DrawBitmapFontText op = new DrawBitmapFontText(text, bitmapFont, start, end, x, y);
+
+ operations.add(op);
+ }
+
+ /**
+ * The name of the class
+ *
+ * @return the name
+ */
+ @NonNull
+ public static String name() {
+ return CLASS_NAME;
+ }
+
+ /**
+ * The OP_CODE for this command
+ *
+ * @return the opcode
+ */
+ public static int id() {
+ return OP_CODE;
+ }
+
+ /**
+ * Writes out the operation to the buffer
+ *
+ * @param buffer write the command to the buffer
+ * @param textID id of the text
+ * @param bitmapFontID id of the bitmap font
+ * @param start Start position
+ * @param end end position
+ * @param x position of where to draw
+ * @param y position of where to draw
+ */
+ public static void apply(
+ @NonNull WireBuffer buffer,
+ int textID,
+ int bitmapFontID,
+ int start,
+ int end,
+ float x,
+ float y) {
+ buffer.start(Operations.DRAW_BITMAP_FONT_TEXT_RUN);
+ buffer.writeInt(textID);
+ buffer.writeInt(bitmapFontID);
+ buffer.writeInt(start);
+ buffer.writeInt(end);
+ buffer.writeFloat(x);
+ buffer.writeFloat(y);
+ }
+
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
+ public static void documentation(@NonNull DocumentationBuilder doc) {
+ doc.operation("Draw Operations", id(), CLASS_NAME)
+ .description("Draw a run of bitmap font text, all in a single direction")
+ .field(DocumentedOperation.INT, "textId", "id of bitmap")
+ .field(DocumentedOperation.INT, "bitmapFontId", "id of the bitmap font")
+ .field(
+ DocumentedOperation.INT,
+ "start",
+ "The start of the text to render. -1=end of string")
+ .field(DocumentedOperation.INT, "end", "The end of the text to render")
+ .field(
+ DocumentedOperation.INT,
+ "contextStart",
+ "the index of the start of the shaping context")
+ .field(
+ DocumentedOperation.INT,
+ "contextEnd",
+ "the index of the end of the shaping context")
+ .field(DocumentedOperation.FLOAT, "x", "The x position at which to draw the text")
+ .field(DocumentedOperation.FLOAT, "y", "The y position at which to draw the text")
+ .field(DocumentedOperation.BOOLEAN, "RTL", "Whether the run is in RTL direction");
+ }
+
+ @Override
+ public void paint(@NonNull PaintContext context) {
+ RemoteContext remoteContext = context.getContext();
+ String textToPaint = remoteContext.getText(mTextID);
+ if (textToPaint == null) {
+ return;
+ }
+ if (mEnd == -1) {
+ if (mStart != 0) {
+ textToPaint = textToPaint.substring(mStart);
+ }
+ } else if (mEnd > textToPaint.length()) {
+ textToPaint = textToPaint.substring(mStart);
+ } else {
+ textToPaint = textToPaint.substring(mStart, mEnd);
+ }
+
+ BitmapFontData bitmapFont = (BitmapFontData) remoteContext.getObject(mBitmapFontID);
+ if (bitmapFont == null) {
+ return;
+ }
+
+ float xPos = mX;
+ int pos = 0;
+ while (pos < textToPaint.length()) {
+ BitmapFontData.Glyph glyph = bitmapFont.lookupGlyph(textToPaint, pos);
+ if (glyph == null) {
+ pos++;
+ continue;
+ }
+
+ pos += glyph.mChars.length();
+ if (glyph.mBitmapId == -1) {
+ // Space is represented by a glyph of -1.
+ xPos += glyph.mMarginLeft + glyph.mMarginRight;
+ continue;
+ }
+
+ xPos += glyph.mMarginLeft;
+ float xPos2 = xPos + glyph.mBitmapWidth;
+ context.drawBitmap(
+ glyph.mBitmapId, xPos, mY + glyph.mMarginTop, xPos2, mY + glyph.mBitmapHeight);
+ xPos = xPos2 + glyph.mMarginRight;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java
new file mode 100644
index 000000000000..eccc00a18308
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionCall.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core.operations;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
+import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression;
+import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** This provides the command to call a floatfunction defined in floatfunction */
+public class FloatFunctionCall extends PaintOperation implements VariableSupport {
+ private static final int OP_CODE = Operations.FUNCTION_CALL;
+ private static final String CLASS_NAME = "FunctionCall";
+ private final int mId;
+ private final float[] mArgs;
+ private final float[] mOutArgs;
+
+ FloatFunctionDefine mFunction;
+
+ @NonNull private ArrayList<Operation> mList = new ArrayList<>();
+
+ @NonNull AnimatedFloatExpression mExp = new AnimatedFloatExpression();
+
+ /**
+ * Create a new FloatFunctionCall operation
+ *
+ * @param id The function to call
+ * @param args the arguments to call it with
+ */
+ public FloatFunctionCall(int id, float[] args) {
+ mId = id;
+ mArgs = args;
+ if (args != null) {
+ mOutArgs = new float[args.length];
+ System.arraycopy(args, 0, mOutArgs, 0, args.length);
+ } else {
+ mOutArgs = null;
+ }
+ }
+
+ @Override
+ public void updateVariables(@NonNull RemoteContext context) {
+ if (mOutArgs != null) {
+ for (int i = 0; i < mArgs.length; i++) {
+ float v = mArgs[i];
+ mOutArgs[i] =
+ (Float.isNaN(v)
+ && !AnimatedFloatExpression.isMathOperator(v)
+ && !NanMap.isDataVariable(v))
+ ? context.getFloat(Utils.idFromNan(v))
+ : v;
+ }
+ }
+ }
+
+ @Override
+ public void registerListening(@NonNull RemoteContext context) {
+ mFunction = (FloatFunctionDefine) context.getObject(mId);
+ if (mArgs != null) {
+ for (int i = 0; i < mArgs.length; i++) {
+ float v = mArgs[i];
+ if (Float.isNaN(v)
+ && !AnimatedFloatExpression.isMathOperator(v)
+ && !NanMap.isDataVariable(v)) {
+ context.listensTo(Utils.idFromNan(v), this);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void write(@NonNull WireBuffer buffer) {
+ apply(buffer, mId, mArgs);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ String str = "callFunction[" + Utils.idString(mId) + "] ";
+ for (int i = 0; i < mArgs.length; i++) {
+ str += ((i == 0) ? "" : " ,") + Utils.floatToString(mArgs[i], mOutArgs[i]);
+ }
+ return str;
+ }
+
+ /**
+ * Write the operation on the buffer
+ *
+ * @param buffer the buffer to write to
+ * @param id the id of the function to call
+ * @param args the arguments to call the function with
+ */
+ public static void apply(@NonNull WireBuffer buffer, int id, @Nullable float[] args) {
+ buffer.start(OP_CODE);
+ buffer.writeInt(id);
+ if (args != null) {
+ buffer.writeInt(args.length);
+ for (int i = 0; i < args.length; i++) {
+ buffer.writeFloat(args[i]);
+ }
+ } else {
+ buffer.writeInt(0);
+ }
+ }
+
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+ int id = buffer.readInt();
+ int argLen = buffer.readInt();
+ float[] args = null;
+ if (argLen > 0) {
+ args = new float[argLen];
+ for (int i = 0; i < argLen; i++) {
+ args[i] = buffer.readFloat();
+ }
+ }
+
+ FloatFunctionCall data = new FloatFunctionCall(id, args);
+ operations.add(data);
+ }
+
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
+ public static void documentation(@NonNull DocumentationBuilder doc) {
+ doc.operation("Data Operations", OP_CODE, CLASS_NAME)
+ .description("Command to call the function")
+ .field(DocumentedOperation.INT, "id", "id of function to call")
+ .field(INT, "argLen", "the number of Arguments")
+ .field(FLOAT_ARRAY, "values", "argLen", "array of float arguments");
+ }
+
+ @NonNull
+ @Override
+ public String deepToString(@NonNull String indent) {
+ return indent + toString();
+ }
+
+ @Override
+ public void paint(@NonNull PaintContext context) {
+ RemoteContext remoteContext = context.getContext();
+ int[] args = mFunction.getArgs();
+ for (int j = 0; j < mOutArgs.length; j++) {
+ remoteContext.loadFloat(args[j], mOutArgs[j]);
+ updateVariables(remoteContext);
+ }
+ mFunction.execute(remoteContext);
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionDefine.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionDefine.java
new file mode 100644
index 000000000000..efd4eecb807e
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatFunctionDefine.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core.operations;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+
+import android.annotation.NonNull;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.Container;
+import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This defines a function Operator. It contains a collection of commands which are then executed by
+ * the FloatFunctionCall command
+ */
+public class FloatFunctionDefine extends Operation implements VariableSupport, Container {
+ private static final int OP_CODE = Operations.FUNCTION_DEFINE;
+ private static final String CLASS_NAME = "FunctionDefine";
+ private final int mId;
+ private final int[] mFloatVarId;
+ @NonNull private ArrayList<Operation> mList = new ArrayList<>();
+
+ @NonNull AnimatedFloatExpression mExp = new AnimatedFloatExpression();
+
+ /**
+ * @param id The id of the function
+ * @param floatVarId the ids of the variables
+ */
+ public FloatFunctionDefine(int id, int[] floatVarId) {
+ mId = id;
+ mFloatVarId = floatVarId;
+ }
+
+ @NonNull
+ @Override
+ public ArrayList<Operation> getList() {
+ return mList;
+ }
+
+ @Override
+ public void updateVariables(@NonNull RemoteContext context) {}
+
+ @Override
+ public void registerListening(@NonNull RemoteContext context) {
+ context.putObject(mId, this);
+ }
+
+ @Override
+ public void write(@NonNull WireBuffer buffer) {
+ apply(buffer, mId, mFloatVarId);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ String str = "FloatFunctionDefine[" + Utils.idString(mId) + "] (";
+ for (int j = 0; j < mFloatVarId.length; j++) {
+ str += "[" + mFloatVarId[j] + "] ";
+ }
+ str += ")";
+ for (Operation operation : mList) {
+ str += " \n " + operation.toString();
+ }
+ return str;
+ }
+
+ /**
+ * Write the operation on the buffer
+ *
+ * @param buffer the buffer to write to
+ * @param id the id of the function
+ * @param varId the ids of the variables
+ */
+ public static void apply(@NonNull WireBuffer buffer, int id, @NonNull int[] varId) {
+ buffer.start(OP_CODE);
+ buffer.writeInt(id);
+ buffer.writeInt(varId.length);
+ for (int i = 0; i < varId.length; i++) {
+ buffer.writeInt(varId[i]);
+ }
+ }
+
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+ int id = buffer.readInt();
+ int varLen = buffer.readInt();
+ int[] varId = new int[varLen];
+ for (int i = 0; i < varId.length; i++) {
+ varId[i] = buffer.readInt();
+ }
+ FloatFunctionDefine data = new FloatFunctionDefine(id, varId);
+ operations.add(data);
+ }
+
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
+ public static void documentation(@NonNull DocumentationBuilder doc) {
+ doc.operation("Data Operations", OP_CODE, CLASS_NAME)
+ .description("Define a function")
+ .field(DocumentedOperation.INT, "id", "The reference of the function")
+ .field(INT, "varLen", "number of arguments to the function")
+ .field(FLOAT_ARRAY, "id", "varLen", "id equations");
+ }
+
+ @NonNull
+ @Override
+ public String deepToString(@NonNull String indent) {
+ return indent + toString();
+ }
+
+ /**
+ * @return the array of id's
+ */
+ public int[] getArgs() {
+ return mFloatVarId;
+ }
+
+ @Override
+ public void apply(@NonNull RemoteContext context) {}
+
+ /**
+ * Execute the function by applying the list of operations
+ *
+ * @param context the current RemoteContext
+ */
+ public void execute(@NonNull RemoteContext context) {
+ for (Operation op : mList) {
+ if (op instanceof VariableSupport) {
+ ((VariableSupport) op).updateVariables(context);
+ }
+
+ context.incrementOpCount();
+ op.apply(context);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java
index 9e891c48c065..ee9e7a4045cb 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java
@@ -39,7 +39,7 @@ import java.util.List;
* for constructing the particles
*/
public class ParticlesCreate extends Operation implements VariableSupport {
- private static final int OP_CODE = Operations.PARTICLE_CREATE;
+ private static final int OP_CODE = Operations.PARTICLE_DEFINE;
private static final String CLASS_NAME = "ParticlesCreate";
private final int mId;
private final float[][] mEquations;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java
index 791079070622..8d19c94df604 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java
@@ -38,7 +38,7 @@ import java.util.ArrayList;
import java.util.List;
/**
- * This provides the mechinism to evolve the particles It consist of a restart equation and a list
+ * This provides the mechanism to evolve the particles It consist of a restart equation and a list
* of equations particle restarts if restart equation > 0
*/
public class ParticlesLoop extends PaintOperation implements VariableSupport, Container {
@@ -159,10 +159,10 @@ public class ParticlesLoop extends PaintOperation implements VariableSupport, Co
/**
* Write the operation on the buffer
*
- * @param buffer
- * @param id
- * @param restart
- * @param equations
+ * @param buffer the buffer to write to
+ * @param id the id of the particle system
+ * @param restart the restart equation
+ * @param equations the equations to evolve the particles
*/
public static void apply(
@NonNull WireBuffer buffer,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java
index bd68d5a8c180..5f505409e254 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java
@@ -289,4 +289,21 @@ public class Utils {
}
return 0;
}
+
+ /**
+ * Convert float alpha, red,g reen, blue to ARGB int
+ *
+ * @param alpha alpha value
+ * @param red red value
+ * @param green green value
+ * @param blue blue value
+ * @return ARGB int
+ */
+ public static int toARGB(float alpha, float red, float green, float blue) {
+ int a = (int) (alpha * 255.0f + 0.5f);
+ int r = (int) (red * 255.0f + 0.5f);
+ int g = (int) (green * 255.0f + 0.5f);
+ int b = (int) (blue * 255.0f + 0.5f);
+ return (a << 24 | r << 16 | g << 8 | b);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
index 8e733ce1d808..96a31aec7dc4 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
@@ -37,13 +37,15 @@ import com.android.internal.widget.remotecompose.core.operations.layout.measure.
import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
+import com.android.internal.widget.remotecompose.core.serialize.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
/** Generic Component class */
public class Component extends PaintOperation
- implements Container, Measurable, SerializableToString {
+ implements Container, Measurable, SerializableToString, Serializable {
private static final boolean DEBUG = false;
@@ -61,7 +63,7 @@ public class Component extends PaintOperation
public boolean mNeedsMeasure = true;
public boolean mNeedsRepaint = false;
@Nullable public AnimateMeasure mAnimateMeasure;
- @NonNull public AnimationSpec mAnimationSpec = new AnimationSpec();
+ @NonNull public AnimationSpec mAnimationSpec = AnimationSpec.DEFAULT;
public boolean mFirstLayout = true;
@NonNull PaintBundle mPaint = new PaintBundle();
@NonNull protected HashSet<ComponentValue> mComponentValues = new HashSet<>();
@@ -318,6 +320,14 @@ public class Component extends PaintOperation
}
}
+ protected AnimationSpec getAnimationSpec() {
+ return mAnimationSpec;
+ }
+
+ protected void setAnimationSpec(@NonNull AnimationSpec animationSpec) {
+ mAnimationSpec = animationSpec;
+ }
+
public enum Visibility {
GONE,
VISIBLE,
@@ -501,16 +511,17 @@ public class Component extends PaintOperation
*
* @param context
* @param document
- * @param x
- * @param y
+ * @param x x location on screen or -1 if unconditional click
+ * @param y y location on screen or -1 if unconditional click
*/
public void onClick(
@NonNull RemoteContext context, @NonNull CoreDocument document, float x, float y) {
- if (!contains(x, y)) {
+ boolean isUnconditional = x == -1 & y == -1;
+ if (!isUnconditional && !contains(x, y)) {
return;
}
- float cx = x - getScrollX();
- float cy = y - getScrollY();
+ float cx = isUnconditional ? -1 : x - getScrollX();
+ float cy = isUnconditional ? -1 : y - getScrollY();
for (Operation op : mList) {
if (op instanceof Component) {
((Component) op).onClick(context, document, cx, cy);
@@ -1035,4 +1046,15 @@ public class Component extends PaintOperation
}
return null;
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ serializer.add("type", getSerializedName());
+ serializer.add("id", mComponentId);
+ serializer.add("x", mX);
+ serializer.add("y", mY);
+ serializer.add("width", mWidth);
+ serializer.add("height", mHeight);
+ serializer.add("visibility", mVisibility);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
index dcd334822010..c517e50f35d3 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
@@ -32,6 +32,7 @@ import com.android.internal.widget.remotecompose.core.operations.MatrixTranslate
import com.android.internal.widget.remotecompose.core.operations.PaintData;
import com.android.internal.widget.remotecompose.core.operations.TextData;
import com.android.internal.widget.remotecompose.core.operations.TouchExpression;
+import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimationSpec;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentModifiers;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ComponentVisibilityOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.DimensionModifierOperation;
@@ -44,6 +45,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.modifier
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthInModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ZIndexModifierOperation;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
import java.util.ArrayList;
@@ -234,6 +236,8 @@ public class LayoutComponent extends Component {
mZIndexModifier = (ZIndexModifierOperation) op;
} else if (op instanceof GraphicsLayerModifierOperation) {
mGraphicsLayerModifier = (GraphicsLayerModifierOperation) op;
+ } else if (op instanceof AnimationSpec) {
+ mAnimationSpec = (AnimationSpec) op;
} else if (op instanceof ScrollDelegate) {
ScrollDelegate scrollDelegate = (ScrollDelegate) op;
if (scrollDelegate.handlesHorizontalScroll()) {
@@ -256,6 +260,16 @@ public class LayoutComponent extends Component {
if (heightInConstraints != null) {
mHeightModifier.setHeightIn(heightInConstraints);
}
+
+ if (mAnimationSpec != AnimationSpec.DEFAULT) {
+ for (int i = 0; i < mChildrenComponents.size(); i++) {
+ Component c = mChildrenComponents.get(i);
+ if (c != null && c.getAnimationSpec() == AnimationSpec.DEFAULT) {
+ c.setAnimationSpec(mAnimationSpec);
+ }
+ }
+ }
+
setWidth(computeModifierDefinedWidth(null));
setHeight(computeModifierDefinedHeight(null));
}
@@ -473,4 +487,14 @@ public class LayoutComponent extends Component {
public ArrayList<Component> getChildrenComponents() {
return mChildrenComponents;
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ super.serialize(serializer);
+ serializer.add("children", mChildrenComponents);
+ serializer.add("paddingLeft", mPaddingLeft);
+ serializer.add("paddingRight", mPaddingRight);
+ serializer.add("paddingTop", mPaddingTop);
+ serializer.add("paddingBottom", mPaddingBottom);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java
index 4977a15e2dc1..a4e8f5c5f18e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java
@@ -94,6 +94,11 @@ public class TouchCancelModifierOperation extends ListActionsOperation implement
return "TouchCancelModifier";
}
+ /**
+ * Write the operation on the buffer
+ *
+ * @param buffer a WireBuffer
+ */
public static void apply(WireBuffer buffer) {
buffer.start(OP_CODE);
}
@@ -108,6 +113,11 @@ public class TouchCancelModifierOperation extends ListActionsOperation implement
operations.add(new TouchCancelModifierOperation());
}
+ /**
+ * Add documentation for this operation
+ *
+ * @param doc a DocumentationBuilder
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, name())
.description(
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java
index 8c51f2eac383..6191bf4e4ad2 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchDownModifierOperation.java
@@ -96,14 +96,30 @@ public class TouchDownModifierOperation extends ListActionsOperation implements
return "TouchModifier";
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ */
public static void apply(WireBuffer buffer) {
buffer.start(OP_CODE);
}
+ /**
+ * Read the operation from the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param operations the list of operations we read so far
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
operations.add(new TouchDownModifierOperation());
}
+ /**
+ * Add documentation for this operation
+ *
+ * @param doc a DocumentationBuilder
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, name())
.description(
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java
index a12c356f7c48..a7e423e67940 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchUpModifierOperation.java
@@ -94,14 +94,30 @@ public class TouchUpModifierOperation extends ListActionsOperation implements To
return "TouchUpModifier";
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ */
public static void apply(WireBuffer buffer) {
buffer.start(OP_CODE);
}
+ /**
+ * Read the operation from the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param operations the list of operations we read so far
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
operations.add(new TouchUpModifierOperation());
}
+ /**
+ * Add documentation for this operation
+ *
+ * @param doc a DocumentationBuilder
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, name())
.description(
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
index d3b3e0e775f2..e5cd485967e8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimateMeasure.java
@@ -38,8 +38,8 @@ public class AnimateMeasure {
private final @NonNull Component mComponent;
private final @NonNull ComponentMeasure mOriginal;
private final @NonNull ComponentMeasure mTarget;
- private int mDuration;
- private int mDurationVisibilityChange = mDuration;
+ private float mDuration;
+ private float mDurationVisibilityChange = mDuration;
private @NonNull AnimationSpec.ANIMATION mEnterAnimation = AnimationSpec.ANIMATION.FADE_IN;
private @NonNull AnimationSpec.ANIMATION mExitAnimation = AnimationSpec.ANIMATION.FADE_OUT;
private int mMotionEasingType = GeneralEasing.CUBIC_STANDARD;
@@ -64,8 +64,8 @@ public class AnimateMeasure {
@NonNull Component component,
@NonNull ComponentMeasure original,
@NonNull ComponentMeasure target,
- int duration,
- int durationVisibilityChange,
+ float duration,
+ float durationVisibilityChange,
@NonNull AnimationSpec.ANIMATION enterAnimation,
@NonNull AnimationSpec.ANIMATION exitAnimation,
int motionEasingType,
@@ -94,6 +94,11 @@ public class AnimateMeasure {
component.mVisibility = target.getVisibility();
}
+ /**
+ * Update the current bounds/visibility/etc given the current time
+ *
+ * @param currentTime the time we use to evaluate the animation
+ */
public void update(long currentTime) {
long elapsed = currentTime - mStartTime;
float motionProgress = elapsed / (float) mDuration;
@@ -347,6 +352,11 @@ public class AnimateMeasure {
return mOriginal.getH() * (1 - mP) + mTarget.getH() * mP;
}
+ /**
+ * Returns the visibility for this measure
+ *
+ * @return the current visibility (possibly interpolated)
+ */
public float getVisibility() {
if (mOriginal.getVisibility() == mTarget.getVisibility()) {
return 1f;
@@ -357,6 +367,12 @@ public class AnimateMeasure {
}
}
+ /**
+ * Set the target values from the given measure
+ *
+ * @param measure the target measure
+ * @param currentTime the current time
+ */
public void updateTarget(@NonNull ComponentMeasure measure, long currentTime) {
mOriginal.setX(getX());
mOriginal.setY(getY());
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
index 6dff4a87088b..6e9de58e354a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java
@@ -24,25 +24,28 @@ import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
import com.android.internal.widget.remotecompose.core.operations.utilities.easing.GeneralEasing;
import java.util.List;
/** Basic component animation spec */
-public class AnimationSpec extends Operation {
+public class AnimationSpec extends Operation implements ModifierOperation {
+ public static final AnimationSpec DEFAULT = new AnimationSpec();
int mAnimationId = -1;
- int mMotionDuration = 300;
+ float mMotionDuration = 300;
int mMotionEasingType = GeneralEasing.CUBIC_STANDARD;
- int mVisibilityDuration = 300;
+ float mVisibilityDuration = 300;
int mVisibilityEasingType = GeneralEasing.CUBIC_STANDARD;
@NonNull ANIMATION mEnterAnimation = ANIMATION.FADE_IN;
@NonNull ANIMATION mExitAnimation = ANIMATION.FADE_OUT;
public AnimationSpec(
int animationId,
- int motionDuration,
+ float motionDuration,
int motionEasingType,
- int visibilityDuration,
+ float visibilityDuration,
int visibilityEasingType,
@NonNull ANIMATION enterAnimation,
@NonNull ANIMATION exitAnimation) {
@@ -70,7 +73,7 @@ public class AnimationSpec extends Operation {
return mAnimationId;
}
- public int getMotionDuration() {
+ public float getMotionDuration() {
return mMotionDuration;
}
@@ -78,7 +81,7 @@ public class AnimationSpec extends Operation {
return mMotionEasingType;
}
- public int getVisibilityDuration() {
+ public float getVisibilityDuration() {
return mVisibilityDuration;
}
@@ -102,6 +105,25 @@ public class AnimationSpec extends Operation {
return "ANIMATION_SPEC (" + mMotionDuration + " ms)";
}
+ @Override
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
+ serializer.append(
+ indent,
+ "ANIMATION_SPEC = ["
+ + getMotionDuration()
+ + ", "
+ + getMotionEasingType()
+ + ", "
+ + getVisibilityDuration()
+ + ", "
+ + getVisibilityEasingType()
+ + ", "
+ + getEnterAnimation()
+ + ", "
+ + getExitAnimation()
+ + "]");
+ }
+
public enum ANIMATION {
FADE_IN,
FADE_OUT,
@@ -156,10 +178,22 @@ public class AnimationSpec extends Operation {
return Operations.ANIMATION_SPEC;
}
+ /**
+ * Returns an int for the given ANIMATION
+ *
+ * @param animation an ANIMATION enum value
+ * @return a corresponding int value
+ */
public static int animationToInt(@NonNull ANIMATION animation) {
return animation.ordinal();
}
+ /**
+ * Maps int value to the corresponding ANIMATION enum values
+ *
+ * @param value int value mapped to the enum
+ * @return the corresponding ANIMATION enum value
+ */
@NonNull
public static ANIMATION intToAnimation(int value) {
switch (value) {
@@ -184,20 +218,32 @@ public class AnimationSpec extends Operation {
}
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param animationId the animation id
+ * @param motionDuration the duration of the motion animation
+ * @param motionEasingType the type of easing for the motion animation
+ * @param visibilityDuration the duration of the visibility animation
+ * @param visibilityEasingType the type of easing for the visibility animation
+ * @param enterAnimation the type of animation when "entering" (newly visible)
+ * @param exitAnimation the type of animation when "exiting" (newly gone)
+ */
public static void apply(
@NonNull WireBuffer buffer,
int animationId,
- int motionDuration,
+ float motionDuration,
int motionEasingType,
- int visibilityDuration,
+ float visibilityDuration,
int visibilityEasingType,
@NonNull ANIMATION enterAnimation,
@NonNull ANIMATION exitAnimation) {
buffer.start(Operations.ANIMATION_SPEC);
buffer.writeInt(animationId);
- buffer.writeInt(motionDuration);
+ buffer.writeFloat(motionDuration);
buffer.writeInt(motionEasingType);
- buffer.writeInt(visibilityDuration);
+ buffer.writeFloat(visibilityDuration);
buffer.writeInt(visibilityEasingType);
buffer.writeInt(animationToInt(enterAnimation));
buffer.writeInt(animationToInt(exitAnimation));
@@ -211,9 +257,9 @@ public class AnimationSpec extends Operation {
*/
public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
int animationId = buffer.readInt();
- int motionDuration = buffer.readInt();
+ float motionDuration = buffer.readFloat();
int motionEasingType = buffer.readInt();
- int visibilityDuration = buffer.readInt();
+ float visibilityDuration = buffer.readFloat();
int visibilityEasingType = buffer.readInt();
ANIMATION enterAnimation = intToAnimation(buffer.readInt());
ANIMATION exitAnimation = intToAnimation(buffer.readInt());
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
index 64e2f004cb65..051579b02cee 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/ParticleAnimation.java
@@ -30,6 +30,15 @@ public class ParticleAnimation {
@NonNull PaintBundle mPaint = new PaintBundle();
+ /**
+ * Animate the particle animation
+ *
+ * @param context the current paint context
+ * @param component the target component
+ * @param start the component's measure at the end of the animation
+ * @param end the component's measure at the end of the animation
+ * @param progress the current animation progress
+ */
public void animate(
@NonNull PaintContext context,
@NonNull Component component,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
index a37f35f0c8d8..35d639e65385 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java
@@ -29,6 +29,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.Componen
import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
import java.util.List;
@@ -191,6 +192,15 @@ public class BoxLayout extends LayoutManager {
return Operations.LAYOUT_BOX;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param componentId the component id
+ * @param animationId the component animation id
+ * @param horizontalPositioning the horizontal positioning rules
+ * @param verticalPositioning the vertical positioning rules
+ */
public static void apply(
@NonNull WireBuffer buffer,
int componentId,
@@ -260,4 +270,28 @@ public class BoxLayout extends LayoutManager {
public void write(@NonNull WireBuffer buffer) {
apply(buffer, mComponentId, mAnimationId, mHorizontalPositioning, mVerticalPositioning);
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ super.serialize(serializer);
+ serializer.add("verticalPositioning", getPositioningString(mVerticalPositioning));
+ serializer.add("horizontalPositioning", getPositioningString(mHorizontalPositioning));
+ }
+
+ private String getPositioningString(int pos) {
+ switch (pos) {
+ case START:
+ return "START";
+ case CENTER:
+ return "CENTER";
+ case END:
+ return "END";
+ case TOP:
+ return "TOP";
+ case BOTTOM:
+ return "BOTTOM";
+ default:
+ return "NONE";
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java
index 0091a47eebfb..8448132cbcc1 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java
@@ -28,6 +28,7 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio
import com.android.internal.widget.remotecompose.core.operations.layout.Component;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
import java.util.List;
@@ -91,6 +92,13 @@ public class CanvasLayout extends BoxLayout {
return Operations.LAYOUT_CANVAS;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param componentId the component id
+ * @param animationId the component animation id
+ */
public static void apply(@NonNull WireBuffer buffer, int componentId, int animationId) {
buffer.start(Operations.LAYOUT_CANVAS);
buffer.writeInt(componentId);
@@ -142,4 +150,27 @@ public class CanvasLayout extends BoxLayout {
public void write(@NonNull WireBuffer buffer) {
apply(buffer, mComponentId, mAnimationId);
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ super.serialize(serializer);
+ serializer.add("", mHorizontalPositioning);
+ }
+
+ private String getPositioningString(int pos) {
+ switch (pos) {
+ case START:
+ return "START";
+ case CENTER:
+ return "CENTER";
+ case END:
+ return "END";
+ case TOP:
+ return "TOP";
+ case BOTTOM:
+ return "BOTTOM";
+ default:
+ return "NONE";
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
index 4d0cbefb0c92..47a55b6ed82a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java
@@ -34,6 +34,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.measure.
import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.HeightInModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.utils.DebugLog;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
import java.util.List;
@@ -218,6 +219,8 @@ public class ColumnLayout extends LayoutManager {
boolean checkWeights = true;
while (checkWeights) {
checkWeights = false;
+ childrenWidth = 0f;
+ childrenHeight = 0f;
boolean hasWeights = false;
float totalWeights = 0f;
for (Component child : mChildrenComponents) {
@@ -477,4 +480,35 @@ public class ColumnLayout extends LayoutManager {
mVerticalPositioning,
mSpacedBy);
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ super.serialize(serializer);
+ serializer.add("verticalPositioning", getPositioningString(mVerticalPositioning));
+ serializer.add("horizontalPositioning", getPositioningString(mHorizontalPositioning));
+ serializer.add("spacedBy", mSpacedBy);
+ }
+
+ private String getPositioningString(int pos) {
+ switch (pos) {
+ case START:
+ return "START";
+ case CENTER:
+ return "CENTER";
+ case END:
+ return "END";
+ case TOP:
+ return "TOP";
+ case BOTTOM:
+ return "BOTTOM";
+ case SPACE_BETWEEN:
+ return "SPACE_BETWEEN";
+ case SPACE_EVENLY:
+ return "SPACE_EVENLY";
+ case SPACE_AROUND:
+ return "SPACE_AROUND";
+ default:
+ return "NONE";
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
index 5b35c4c70702..e93cbd74b0b5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java
@@ -34,6 +34,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.measure.
import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.WidthInModifierOperation;
import com.android.internal.widget.remotecompose.core.operations.layout.utils.DebugLog;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
import java.util.List;
@@ -218,6 +219,8 @@ public class RowLayout extends LayoutManager {
while (checkWeights) {
checkWeights = false;
+ childrenWidth = 0f;
+ childrenHeight = 0f;
boolean hasWeights = false;
float totalWeights = 0f;
for (Component child : mChildrenComponents) {
@@ -481,4 +484,35 @@ public class RowLayout extends LayoutManager {
mVerticalPositioning,
mSpacedBy);
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ super.serialize(serializer);
+ serializer.add("verticalPositioning", getPositioningString(mVerticalPositioning));
+ serializer.add("horizontalPositioning", getPositioningString(mHorizontalPositioning));
+ serializer.add("spacedBy", mSpacedBy);
+ }
+
+ private String getPositioningString(int pos) {
+ switch (pos) {
+ case START:
+ return "START";
+ case CENTER:
+ return "CENTER";
+ case END:
+ return "END";
+ case TOP:
+ return "TOP";
+ case BOTTOM:
+ return "BOTTOM";
+ case SPACE_BETWEEN:
+ return "SPACE_BETWEEN";
+ case SPACE_EVENLY:
+ return "SPACE_EVENLY";
+ case SPACE_AROUND:
+ return "SPACE_AROUND";
+ default:
+ return "NONE";
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java
index 3044797b17c9..ee16bc2f4459 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java
@@ -30,6 +30,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.LayoutCo
import com.android.internal.widget.remotecompose.core.operations.layout.measure.ComponentMeasure;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.MeasurePass;
import com.android.internal.widget.remotecompose.core.operations.layout.measure.Size;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
import java.util.ArrayList;
import java.util.HashMap;
@@ -81,6 +82,7 @@ public class StateLayout extends LayoutManager {
hideLayoutsOtherThan(currentLayoutIndex);
}
+ /** Traverse the list of children and identify animated components across states */
public void findAnimatedComponents() {
for (int i = 0; i < mChildrenComponents.size(); i++) {
Component cs = mChildrenComponents.get(i);
@@ -105,6 +107,10 @@ public class StateLayout extends LayoutManager {
collapsePaintedComponents();
}
+ /**
+ * Traverse the list of components in different states, and if they are similar pick the first
+ * component for painting in all states.
+ */
public void collapsePaintedComponents() {
int numStates = mChildrenComponents.size();
for (Integer id : statePaintedComponents.keySet()) {
@@ -346,6 +352,11 @@ public class StateLayout extends LayoutManager {
measuredLayoutIndex = currentLayoutIndex;
}
+ /**
+ * Hides all layouts that are not the one with the given id
+ *
+ * @param idx the layout id
+ */
public void hideLayoutsOtherThan(int idx) {
int index = 0;
for (Component pane : mChildrenComponents) {
@@ -360,6 +371,12 @@ public class StateLayout extends LayoutManager {
}
}
+ /**
+ * Returns the layout with the given id
+ *
+ * @param idx the component id
+ * @return the LayoutManager with the given id, or the first child of StateLayout if not found
+ */
public @NonNull LayoutManager getLayout(int idx) {
int index = 0;
for (Component pane : mChildrenComponents) {
@@ -485,6 +502,7 @@ public class StateLayout extends LayoutManager {
}
}
+ /** Check if we are at the end of the transition, and if so handles it. */
public void checkEndOfTransition() {
LayoutManager currentLayout = getLayout(measuredLayoutIndex);
LayoutManager previousLayout = getLayout(previousLayoutIndex);
@@ -536,10 +554,16 @@ public class StateLayout extends LayoutManager {
return "STATE_LAYOUT";
}
- // companion object {
- // fun documentation(doc: OrigamiDocumentation) {}
- // }
-
+ /**
+ * write the operation to the buffer
+ *
+ * @param buffer the current buffer
+ * @param componentId the component id
+ * @param animationId the animation id if there's one, -1 otherwise.
+ * @param horizontalPositioning the horizontal positioning rule
+ * @param verticalPositioning the vertical positioning rule
+ * @param indexId the current index
+ */
public static void apply(
@NonNull WireBuffer buffer,
int componentId,
@@ -570,4 +594,10 @@ public class StateLayout extends LayoutManager {
operations.add(
new StateLayout(null, componentId, animationId, 0f, 0f, 100f, 100f, indexId));
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ super.serialize(serializer);
+ serializer.add("indexId", mIndexId);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java
index 8157ea05ec45..e8e95db8141d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java
@@ -34,6 +34,7 @@ import com.android.internal.widget.remotecompose.core.operations.layout.measure.
import com.android.internal.widget.remotecompose.core.operations.paint.PaintBundle;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
import com.android.internal.widget.remotecompose.core.semantics.AccessibleComponent;
+import com.android.internal.widget.remotecompose.core.serialize.MapSerializer;
import java.util.List;
@@ -331,6 +332,20 @@ public class TextLayout extends LayoutManager implements VariableSupport, Access
return Operations.LAYOUT_TEXT;
}
+ /**
+ * Write the operation in the buffer
+ *
+ * @param buffer the WireBuffer we write on
+ * @param componentId the component id
+ * @param animationId the animation id (-1 if not set)
+ * @param textId the text id
+ * @param color the text color
+ * @param fontSize the font size
+ * @param fontStyle the font style
+ * @param fontWeight the font weight
+ * @param fontFamilyId the font family id
+ * @param textAlign the alignment rules
+ */
public static void apply(
@NonNull WireBuffer buffer,
int componentId,
@@ -418,4 +433,16 @@ public class TextLayout extends LayoutManager implements VariableSupport, Access
mFontFamilyId,
mTextAlign);
}
+
+ @Override
+ public void serialize(MapSerializer serializer) {
+ super.serialize(serializer);
+ serializer.add("textId", mTextId);
+ serializer.add("color", mColor);
+ serializer.add("fontSize", mFontSize);
+ serializer.add("fontStyle", mFontStyle);
+ serializer.add("fontWeight", mFontWeight);
+ serializer.add("fontFamilyId", mFontFamilyId);
+ serializer.add("textAlign", mTextAlign);
+ }
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
index 82f23cdcf766..11ed9f435070 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/ComponentMeasure.java
@@ -92,6 +92,11 @@ public class ComponentMeasure {
component.mVisibility);
}
+ /**
+ * Initialize this ComponentMeasure from another ComponentMeasure instance.
+ *
+ * @param m the ComponentMeasure to copy from
+ */
public void copyFrom(@NonNull ComponentMeasure m) {
mX = m.mX;
mY = m.mY;
@@ -100,6 +105,12 @@ public class ComponentMeasure {
mVisibility = m.mVisibility;
}
+ /**
+ * Returns true if the ComponentMeasure passed is identical to us
+ *
+ * @param m the ComponentMeasure to check
+ * @return true if the passed ComponentMeasure is identical to ourself
+ */
public boolean same(@NonNull ComponentMeasure m) {
return mX == m.mX && mY == m.mY && mW == m.mW && mH == m.mH && mVisibility == m.mVisibility;
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
index 5cfb1b43cf15..b14f2d9f8a94 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/measure/MeasurePass.java
@@ -28,10 +28,17 @@ import java.util.HashMap;
public class MeasurePass {
@NonNull HashMap<Integer, ComponentMeasure> mList = new HashMap<>();
+ /** Clear the MeasurePass */
public void clear() {
mList.clear();
}
+ /**
+ * Add a ComponentMeasure to the MeasurePass
+ *
+ * @param measure the ComponentMeasure to add
+ * @throws Exception
+ */
public void add(@NonNull ComponentMeasure measure) throws Exception {
if (measure.mId == -1) {
throw new Exception("Component has no id!");
@@ -39,10 +46,22 @@ public class MeasurePass {
mList.put(measure.mId, measure);
}
+ /**
+ * Returns true if the current MeasurePass already contains a ComponentMeasure for the given id.
+ *
+ * @param id
+ * @return
+ */
public boolean contains(int id) {
return mList.containsKey(id);
}
+ /**
+ * return the ComponentMeasure associated with a given component
+ *
+ * @param c the Component
+ * @return the associated ComponentMeasure
+ */
public @NonNull ComponentMeasure get(@NonNull Component c) {
if (!mList.containsKey(c.getComponentId())) {
ComponentMeasure measure =
@@ -54,6 +73,12 @@ public class MeasurePass {
return mList.get(c.getComponentId());
}
+ /**
+ * Returns the ComponentMeasure associated with the id, creating one if none exists.
+ *
+ * @param id the component id
+ * @return the associated ComponentMeasure
+ */
public @NonNull ComponentMeasure get(int id) {
if (!mList.containsKey(id)) {
ComponentMeasure measure =
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
index b4240d0e08a7..ac23db0ed599 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java
@@ -130,6 +130,20 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer the WireBuffer
+ * @param x x coordinate of the background rect
+ * @param y y coordinate of the background rect
+ * @param width width of the background rect
+ * @param height height of the background rect
+ * @param r red component of the background color
+ * @param g green component of the background color
+ * @param b blue component of the background color
+ * @param a alpha component of the background color
+ * @param shapeType the shape of the background (RECTANGLE=0, CIRCLE=1)
+ */
public static void apply(
@NonNull WireBuffer buffer,
float x,
@@ -205,6 +219,6 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation {
.field(FLOAT, "g", "")
.field(FLOAT, "b", "")
.field(FLOAT, "a", "")
- .field(FLOAT, "shapeType", "");
+ .field(FLOAT, "shapeType", "0 for RECTANGLE, 1 for CIRCLE");
}
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
index df30d9f615e5..06c21bd49f33 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java
@@ -176,6 +176,22 @@ public class BorderModifierOperation extends DecoratorModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer the WireBuffer
+ * @param x x coordinate of the border rect
+ * @param y y coordinate of the border rect
+ * @param width width of the border rect
+ * @param height height of the border rect
+ * @param borderWidth the width of the border outline
+ * @param roundedCorner rounded corner value in pixels
+ * @param r red component of the border color
+ * @param g green component of the border color
+ * @param b blue component of the border color
+ * @param a alpha component of the border color
+ * @param shapeType the shape type (0 = RECTANGLE, 1 = CIRCLE)
+ */
public static void apply(
@NonNull WireBuffer buffer,
float x,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
index b27fb9200398..ce4449355434 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java
@@ -76,6 +76,11 @@ public class ClipRectModifierOperation extends DecoratorModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer the WireBuffer
+ */
public static void apply(@NonNull WireBuffer buffer) {
buffer.start(OP_CODE);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
index a1609ace2138..dd27f8b6cfe6 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentModifiers.java
@@ -21,6 +21,7 @@ import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.PaintOperation;
import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.SerializableToString;
import com.android.internal.widget.remotecompose.core.VariableSupport;
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.operations.MatrixRestore;
@@ -36,7 +37,7 @@ import java.util.ArrayList;
/** Maintain a list of modifiers */
public class ComponentModifiers extends PaintOperation
- implements DecoratorComponent, ClickHandler, TouchHandler {
+ implements DecoratorComponent, ClickHandler, TouchHandler, SerializableToString {
@NonNull ArrayList<ModifierOperation> mList = new ArrayList<>();
@NonNull
@@ -68,6 +69,7 @@ public class ComponentModifiers extends PaintOperation
// nothing
}
+ @Override
public void serializeToString(int indent, @NonNull StringSerializer serializer) {
serializer.append(indent, "MODIFIERS");
for (ModifierOperation m : mList) {
@@ -75,10 +77,20 @@ public class ComponentModifiers extends PaintOperation
}
}
+ /**
+ * Add a ModifierOperation
+ *
+ * @param operation a ModifierOperation
+ */
public void add(@NonNull ModifierOperation operation) {
mList.add(operation);
}
+ /**
+ * Returns the size of the modifier list
+ *
+ * @return number of modifiers
+ */
public int size() {
return mList.size();
}
@@ -133,6 +145,11 @@ public class ComponentModifiers extends PaintOperation
}
}
+ /**
+ * Add the operations to this ComponentModifier
+ *
+ * @param operations list of ModifierOperation
+ */
public void addAll(@NonNull ArrayList<ModifierOperation> operations) {
mList.addAll(operations);
}
@@ -197,6 +214,11 @@ public class ComponentModifiers extends PaintOperation
}
}
+ /**
+ * Returns true if we have a horizontal scroll modifier
+ *
+ * @return true if we have a horizontal scroll modifier, false otherwise
+ */
public boolean hasHorizontalScroll() {
for (ModifierOperation op : mList) {
if (op instanceof ScrollModifierOperation) {
@@ -209,6 +231,11 @@ public class ComponentModifiers extends PaintOperation
return false;
}
+ /**
+ * Returns true if we have a vertical scroll modifier
+ *
+ * @return true if we have a vertical scroll modifier, false otherwise
+ */
public boolean hasVerticalScroll() {
for (ModifierOperation op : mList) {
if (op instanceof ScrollModifierOperation) {
@@ -221,6 +248,12 @@ public class ComponentModifiers extends PaintOperation
return false;
}
+ /**
+ * Set the horizontal scroll dimension (if we have a scroll modifier)
+ *
+ * @param hostDimension the host component horizontal dimension
+ * @param contentDimension the content horizontal dimension
+ */
public void setHorizontalScrollDimension(float hostDimension, float contentDimension) {
for (ModifierOperation op : mList) {
if (op instanceof ScrollModifierOperation) {
@@ -232,6 +265,12 @@ public class ComponentModifiers extends PaintOperation
}
}
+ /**
+ * Set the vertical scroll dimension (if we have a scroll modifier)
+ *
+ * @param hostDimension the host component vertical dimension
+ * @param contentDimension the content vertical dimension
+ */
public void setVerticalScrollDimension(float hostDimension, float contentDimension) {
for (ModifierOperation op : mList) {
if (op instanceof ScrollModifierOperation) {
@@ -243,6 +282,11 @@ public class ComponentModifiers extends PaintOperation
}
}
+ /**
+ * Returns the horizontal scroll dimension if we have a scroll modifier
+ *
+ * @return the horizontal scroll dimension, or 0 if no scroll modifier
+ */
public float getHorizontalScrollDimension() {
for (ModifierOperation op : mList) {
if (op instanceof ScrollModifierOperation) {
@@ -255,6 +299,11 @@ public class ComponentModifiers extends PaintOperation
return 0f;
}
+ /**
+ * Returns the vertical scroll dimension if we have a scroll modifier
+ *
+ * @return the vertical scroll dimension, or 0 if no scroll modifier
+ */
public float getVerticalScrollDimension() {
for (ModifierOperation op : mList) {
if (op instanceof ScrollModifierOperation) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java
index c377b756ff38..dd22391c43ac 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java
@@ -52,6 +52,11 @@ public class ComponentVisibilityOperation extends Operation
return "ComponentVisibilityOperation(" + mVisibilityId + ")";
}
+ /**
+ * Returns the serialized name for this operation
+ *
+ * @return the serialized name
+ */
@NonNull
public String serializedName() {
return "COMPONENT_VISIBILITY";
@@ -74,6 +79,12 @@ public class ComponentVisibilityOperation extends Operation
@Override
public void write(@NonNull WireBuffer buffer) {}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param valueId visibility value
+ */
public static void apply(@NonNull WireBuffer buffer, int valueId) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionInModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionInModifierOperation.java
new file mode 100644
index 000000000000..7c9acfe8d2e6
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionInModifierOperation.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core.operations.layout.modifiers;
+
+import android.annotation.NonNull;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.operations.Utils;
+import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
+
+/** Helper class to set the min / max dimension on a component */
+public class DimensionInModifierOperation extends Operation
+ implements ModifierOperation, VariableSupport {
+ int mOpCode = -1;
+
+ float mV1;
+ float mV2;
+ float mValue1;
+ float mValue2;
+
+ public DimensionInModifierOperation(int opcode, float min, float max) {
+ mOpCode = opcode;
+ mValue1 = min;
+ mValue2 = max;
+ if (!Float.isNaN(mValue1)) {
+ mV1 = mValue1;
+ }
+ if (!Float.isNaN(mValue2)) {
+ mV2 = mValue2;
+ }
+ }
+
+ @Override
+ public void updateVariables(@NonNull RemoteContext context) {
+ mV1 = Float.isNaN(mValue1) ? context.getFloat(Utils.idFromNan(mValue1)) : mValue1;
+ mV2 = Float.isNaN(mValue2) ? context.getFloat(Utils.idFromNan(mValue2)) : mValue2;
+ if (mV1 != -1) {
+ mV1 = mV1 * context.getDensity();
+ }
+ if (mV2 != -1) {
+ mV2 = mV2 * context.getDensity();
+ }
+ }
+
+ @Override
+ public void registerListening(@NonNull RemoteContext context) {
+ if (Float.isNaN(mValue1)) {
+ context.listensTo(Utils.idFromNan(mValue1), this);
+ }
+ if (Float.isNaN(mValue2)) {
+ context.listensTo(Utils.idFromNan(mValue2), this);
+ }
+ }
+
+ @Override
+ public void write(@NonNull WireBuffer buffer) {
+ // nothing
+ }
+
+ @Override
+ public void apply(@NonNull RemoteContext context) {
+ // nothing
+ }
+
+ @NonNull
+ @Override
+ public String deepToString(@NonNull String indent) {
+ return indent + toString();
+ }
+
+ /**
+ * Returns the min value
+ *
+ * @return minimum value
+ */
+ public float getMin() {
+ return mV1;
+ }
+
+ /**
+ * Returns the max value
+ *
+ * @return maximum value
+ */
+ public float getMax() {
+ return mV2;
+ }
+
+ @Override
+ public void serializeToString(int indent, @NonNull StringSerializer serializer) {
+ serializer.append(indent, "WIDTH_IN = [" + getMin() + ", " + getMax() + "]");
+ }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
index b11deae3d196..88449c4a9016 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java
@@ -104,6 +104,11 @@ public abstract class DimensionModifierOperation extends Operation
}
}
+ /**
+ * Returns true if the dimension is set using a weight
+ *
+ * @return true if using weight, false otherwise
+ */
public boolean hasWeight() {
return mType == Type.WEIGHT;
}
@@ -136,6 +141,11 @@ public abstract class DimensionModifierOperation extends Operation
mOutValue = mValue = value;
}
+ /**
+ * Returns the serialized name for this operation
+ *
+ * @return the serialized name
+ */
@NonNull
public String serializedName() {
return "DIMENSION";
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java
index 15c2f46093d2..dc5918037946 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java
@@ -222,6 +222,26 @@ public class GraphicsLayerModifierOperation extends DecoratorModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param scaleX scaleX of the layer
+ * @param scaleY scaleY of the layer
+ * @param rotationX rotationX of the layer
+ * @param rotationY rotationY of the layer
+ * @param rotationZ rotationZ of the layer
+ * @param shadowElevation the shadow elevation
+ * @param transformOriginX the X origin of the transformations
+ * @param transformOriginY the Y origin of the transformations
+ * @param alpha the alpha of the layer
+ * @param cameraDistance the camera distance
+ * @param blendMode blending mode of the layer
+ * @param spotShadowColorId the spot shadow color id
+ * @param ambientShadowColorId the ambient shadow color id
+ * @param colorFilterId the color filter id
+ * @param renderEffectId the render effect id
+ */
public static void apply(
WireBuffer buffer,
float scaleX,
@@ -257,6 +277,12 @@ public class GraphicsLayerModifierOperation extends DecoratorModifierOperation {
buffer.writeInt(renderEffectId);
}
+ /**
+ * Read the operation from the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param operations the list of operations read so far
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
float scaleX = buffer.readFloat();
float scaleY = buffer.readFloat();
@@ -292,6 +318,11 @@ public class GraphicsLayerModifierOperation extends DecoratorModifierOperation {
renderEffectId));
}
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the GraphicsLayer Modifier")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java
index c19bd2f6b7c0..cc32f2699dfe 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightInModifierOperation.java
@@ -19,47 +19,37 @@ import android.annotation.NonNull;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
-import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
-import com.android.internal.widget.remotecompose.core.operations.DrawBase2;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
import java.util.List;
/** Set the min / max height dimension on a component */
-public class HeightInModifierOperation extends DrawBase2 implements ModifierOperation {
+public class HeightInModifierOperation extends DimensionInModifierOperation {
private static final int OP_CODE = Operations.MODIFIER_HEIGHT_IN;
public static final String CLASS_NAME = "HeightInModifierOperation";
- /**
- * Read this operation and add it to the list of operations
- *
- * @param buffer the buffer to read
- * @param operations the list of operations that will be added to
- */
- public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
- Maker m = HeightInModifierOperation::new;
- read(m, buffer, operations);
+ public HeightInModifierOperation(float min, float max) {
+ super(OP_CODE, min, max);
}
- /**
- * Returns the min value
- *
- * @return minimum value
- */
- public float getMin() {
- return mV1;
+ @Override
+ public void write(@NonNull WireBuffer buffer) {
+ apply(buffer, getMin(), getMax());
}
/**
- * Returns the max value
+ * Read this operation and add it to the list of operations
*
- * @return maximum value
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
*/
- public float getMax() {
- return mV2;
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+ float v1 = buffer.readFloat();
+ float v2 = buffer.readFloat();
+ operations.add(new HeightInModifierOperation(v1, v2));
}
/**
@@ -81,11 +71,6 @@ public class HeightInModifierOperation extends DrawBase2 implements ModifierOper
return CLASS_NAME;
}
- @Override
- protected void write(@NonNull WireBuffer buffer, float v1, float v2) {
- apply(buffer, v1, v2);
- }
-
/**
* Populate the documentation with a description of this operation
*
@@ -98,14 +83,6 @@ public class HeightInModifierOperation extends DrawBase2 implements ModifierOper
.field(DocumentedOperation.FLOAT, "max", "The maximum height, -1 if not applied");
}
- public HeightInModifierOperation(float min, float max) {
- super(min, max);
- mName = CLASS_NAME;
- }
-
- @Override
- public void paint(@NonNull PaintContext context) {}
-
/**
* Writes out the HeightInModifier to the buffer
*
@@ -114,7 +91,9 @@ public class HeightInModifierOperation extends DrawBase2 implements ModifierOper
* @param y1 start y of the DrawOval
*/
public static void apply(@NonNull WireBuffer buffer, float x1, float y1) {
- write(buffer, OP_CODE, x1, y1);
+ buffer.start(OP_CODE);
+ buffer.writeFloat(x1);
+ buffer.writeFloat(y1);
}
@Override
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
index 4b50a916b9cd..154740d5536c 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java
@@ -52,6 +52,13 @@ public class HeightModifierOperation extends DimensionModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param type the type of dimension rule (DimensionModifierOperation.Type)
+ * @param value the value of the dimension
+ */
public static void apply(@NonNull WireBuffer buffer, int type, float value) {
buffer.start(OP_CODE);
buffer.writeInt(type);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java
index 2e9d6619d011..09e2228b847a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java
@@ -23,6 +23,7 @@ import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.SerializableToString;
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
import com.android.internal.widget.remotecompose.core.operations.layout.ActionOperation;
@@ -32,7 +33,8 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin
import java.util.List;
/** Capture a host action information. This can be triggered on eg. a click. */
-public class HostActionOperation extends Operation implements ActionOperation {
+public class HostActionOperation extends Operation
+ implements ActionOperation, SerializableToString {
private static final int OP_CODE = Operations.HOST_ACTION;
int mActionId = -1;
@@ -51,6 +53,11 @@ public class HostActionOperation extends Operation implements ActionOperation {
return mActionId;
}
+ /**
+ * Returns the serialized name for this operation
+ *
+ * @return the serialized name
+ */
@NonNull
public String serializedName() {
return "HOST_ACTION";
@@ -83,6 +90,12 @@ public class HostActionOperation extends Operation implements ActionOperation {
context.runAction(mActionId, "");
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param actionId the action id
+ */
public static void apply(@NonNull WireBuffer buffer, int actionId) {
buffer.start(OP_CODE);
buffer.writeInt(actionId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java
index 49ef58e0fe53..8a8809c653f8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java
@@ -57,6 +57,11 @@ public class HostNamedActionOperation extends Operation implements ActionOperati
return "HostNamedActionOperation(" + mTextId + " : " + mValueId + ")";
}
+ /**
+ * Name used during serialization
+ *
+ * @return the serialized name for this operation
+ */
@NonNull
public String serializedName() {
return "HOST_NAMED_ACTION";
@@ -105,6 +110,14 @@ public class HostNamedActionOperation extends Operation implements ActionOperati
context.runNamedAction(mTextId, value);
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param textId the text id of the action
+ * @param type the type of the action
+ * @param valueId the value id associated with the action
+ */
public static void apply(@NonNull WireBuffer buffer, int textId, int type, int valueId) {
buffer.start(OP_CODE);
buffer.writeInt(textId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java
index 9588e99a65b6..4ad11d267406 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/MarqueeModifierOperation.java
@@ -110,6 +110,12 @@ public class MarqueeModifierOperation extends DecoratorModifierOperation impleme
mVelocity);
}
+ /**
+ * Serialize the string
+ *
+ * @param indent padding to display
+ * @param serializer append the string
+ */
// @Override
public void serializeToString(int indent, StringSerializer serializer) {
serializer.append(indent, "MARQUEE = [" + mIterations + "]");
@@ -153,14 +159,35 @@ public class MarqueeModifierOperation extends DecoratorModifierOperation impleme
return "MarqueeModifierOperation(" + mIterations + ")";
}
+ /**
+ * Name of the operation
+ *
+ * @return name
+ */
public static String name() {
return CLASS_NAME;
}
+ /**
+ * id of the operation
+ *
+ * @return the operation id
+ */
public static int id() {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param iterations the number of iterations
+ * @param animationMode animation mode
+ * @param repeatDelayMillis repeat delay in ms
+ * @param initialDelayMillis initial delay before the marquee start in ms
+ * @param spacing the spacing between marquee
+ * @param velocity the velocity of the marquee animation
+ */
public static void apply(
WireBuffer buffer,
int iterations,
@@ -178,6 +205,12 @@ public class MarqueeModifierOperation extends DecoratorModifierOperation impleme
buffer.writeFloat(velocity);
}
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
int iterations = buffer.readInt();
int animationMode = buffer.readInt();
@@ -195,6 +228,11 @@ public class MarqueeModifierOperation extends DecoratorModifierOperation impleme
velocity));
}
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("specify a Marquee Modifier")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java
index f8926fef56fa..a86fb2c1f6a5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java
@@ -22,5 +22,11 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin
/** Represents a modifier */
public interface ModifierOperation extends OperationInterface {
+ /**
+ * Serialize the string
+ *
+ * @param indent padding to display
+ * @param serializer append the string
+ */
void serializeToString(int indent, @NonNull StringSerializer serializer);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java
index 42719478faf0..2cd2728f0720 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java
@@ -65,6 +65,12 @@ public class OffsetModifierOperation extends DecoratorModifierOperation {
apply(buffer, mX, mY);
}
+ /**
+ * Serialize the string
+ *
+ * @param indent padding to display
+ * @param serializer append the string
+ */
// @Override
public void serializeToString(int indent, StringSerializer serializer) {
serializer.append(indent, "OFFSET = [" + mX + ", " + mY + "]");
@@ -110,18 +116,36 @@ public class OffsetModifierOperation extends DecoratorModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param x x offset
+ * @param y y offset
+ */
public static void apply(WireBuffer buffer, float x, float y) {
buffer.start(OP_CODE);
buffer.writeFloat(x);
buffer.writeFloat(y);
}
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
float x = buffer.readFloat();
float y = buffer.readFloat();
operations.add(new OffsetModifierOperation(x, y));
}
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the Offset Modifier")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
index bcfbdd68472f..3225d5c6f92c 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java
@@ -132,6 +132,15 @@ public class PaddingModifierOperation extends Operation implements ModifierOpera
return Operations.MODIFIER_PADDING;
}
+ /**
+ * Write operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param left left padding
+ * @param top top padding
+ * @param right right padding
+ * @param bottom bottom padding
+ */
public static void apply(
@NonNull WireBuffer buffer, float left, float top, float right, float bottom) {
buffer.start(Operations.MODIFIER_PADDING);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java
index fe074e4754e2..9787d9b4b399 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RippleModifierOperation.java
@@ -143,19 +143,40 @@ public class RippleModifierOperation extends DecoratorModifierOperation implemen
serializer.append(indent, "RIPPLE_MODIFIER");
}
+ /**
+ * The operation name
+ *
+ * @return operation name
+ */
@NonNull
public static String name() {
return "RippleModifier";
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ */
public static void apply(@NonNull WireBuffer buffer) {
buffer.start(OP_CODE);
}
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
operations.add(new RippleModifierOperation());
}
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
public static void documentation(@NonNull DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, name())
.description(
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java
index 8950579354b7..76b3373a52d9 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java
@@ -135,6 +135,12 @@ public class ScrollModifierOperation extends ListActionsOperation
apply(buffer, mDirection, mPositionExpression, mMax, mNotchMax);
}
+ /**
+ * Serialize the string
+ *
+ * @param indent padding to display
+ * @param serializer append the string
+ */
// @Override
public void serializeToString(int indent, StringSerializer serializer) {
serializer.append(indent, "SCROLL = [" + mDirection + "]");
@@ -190,6 +196,15 @@ public class ScrollModifierOperation extends ListActionsOperation
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param direction direction of the scroll (HORIZONTAL, VERTICAL)
+ * @param position the current position
+ * @param max the maximum position
+ * @param notchMax the maximum notch
+ */
public static void apply(
WireBuffer buffer, int direction, float position, float max, float notchMax) {
buffer.start(OP_CODE);
@@ -199,6 +214,12 @@ public class ScrollModifierOperation extends ListActionsOperation
buffer.writeFloat(notchMax);
}
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
int direction = buffer.readInt();
float position = buffer.readFloat();
@@ -207,6 +228,11 @@ public class ScrollModifierOperation extends ListActionsOperation
operations.add(new ScrollModifierOperation(direction, position, max, notchMax));
}
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define a Scroll Modifier")
@@ -300,12 +326,24 @@ public class ScrollModifierOperation extends ListActionsOperation
public void onTouchCancel(
RemoteContext context, CoreDocument document, Component component, float x, float y) {}
+ /**
+ * Set the horizontal scroll dimension
+ *
+ * @param hostDimension the horizontal host dimension
+ * @param contentDimension the horizontal content dimension
+ */
public void setHorizontalScrollDimension(float hostDimension, float contentDimension) {
mHostDimension = hostDimension;
mContentDimension = contentDimension;
mMaxScrollX = contentDimension - hostDimension;
}
+ /**
+ * Set the vertical scroll dimension
+ *
+ * @param hostDimension the vertical host dimension
+ * @param contentDimension the vertical content dimension
+ */
public void setVerticalScrollDimension(float hostDimension, float contentDimension) {
mHostDimension = hostDimension;
mContentDimension = contentDimension;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java
index b6977a035c9e..d625900fcf2e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java
@@ -49,6 +49,11 @@ public class ValueFloatChangeActionOperation extends Operation implements Action
return "ValueFloatChangeActionOperation(" + mTargetValueId + ")";
}
+ /**
+ * The name of the operation used during serialization
+ *
+ * @return the operation serialized name
+ */
public String serializedName() {
return "VALUE_FLOAT_CHANGE";
}
@@ -76,18 +81,36 @@ public class ValueFloatChangeActionOperation extends Operation implements Action
context.overrideFloat(mTargetValueId, mValue);
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param valueId the value id
+ * @param value the value to set
+ */
public static void apply(WireBuffer buffer, int valueId, float value) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
buffer.writeFloat(value);
}
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
int valueId = buffer.readInt();
float value = buffer.readFloat();
operations.add(new ValueFloatChangeActionOperation(valueId, value));
}
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Layout Operations", OP_CODE, "ValueFloatChangeActionOperation")
.description(
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java
index 766271a70ce4..3f26c5e5575b 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java
@@ -50,6 +50,11 @@ public class ValueFloatExpressionChangeActionOperation extends Operation
return "ValueFloatExpressionChangeActionOperation(" + mTargetValueId + ")";
}
+ /**
+ * The name of the operation used during serialization
+ *
+ * @return the operation serialized name
+ */
@NonNull
public String serializedName() {
return "VALUE_FLOAT_EXPRESSION_CHANGE";
@@ -83,6 +88,13 @@ public class ValueFloatExpressionChangeActionOperation extends Operation
document.evaluateFloatExpression(mValueExpressionId, mTargetValueId, context);
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param valueId the value id
+ * @param value the value to set
+ */
public static void apply(@NonNull WireBuffer buffer, int valueId, int value) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java
index 60166a7b2102..8c5bb6fdb268 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java
@@ -49,6 +49,11 @@ public class ValueIntegerChangeActionOperation extends Operation implements Acti
return "ValueChangeActionOperation(" + mTargetValueId + ")";
}
+ /**
+ * The name of the operation used during serialization
+ *
+ * @return the operation serialized name
+ */
@NonNull
public String serializedName() {
return "VALUE_INTEGER_CHANGE";
@@ -81,6 +86,13 @@ public class ValueIntegerChangeActionOperation extends Operation implements Acti
context.overrideInteger(mTargetValueId, mValue);
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param valueId the value id
+ * @param value the value to set
+ */
public static void apply(@NonNull WireBuffer buffer, int valueId, int value) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java
index 502508058465..00c80f12aaba 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java
@@ -50,6 +50,11 @@ public class ValueIntegerExpressionChangeActionOperation extends Operation
return "ValueIntegerExpressionChangeActionOperation(" + mTargetValueId + ")";
}
+ /**
+ * The name of the operation used during serialization
+ *
+ * @return the operation serialized name
+ */
@NonNull
public String serializedName() {
return "VALUE_INTEGER_EXPRESSION_CHANGE";
@@ -83,6 +88,13 @@ public class ValueIntegerExpressionChangeActionOperation extends Operation
document.evaluateIntExpression(mValueExpressionId, (int) mTargetValueId, context);
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param valueId the long id pointing to an int value
+ * @param value the value to set (long id)`
+ */
public static void apply(@NonNull WireBuffer buffer, long valueId, long value) {
buffer.start(OP_CODE);
buffer.writeLong(valueId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java
index 8093bb3c64ec..57e30d4126ba 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java
@@ -53,6 +53,11 @@ public class ValueStringChangeActionOperation extends Operation implements Actio
return mTargetValueId;
}
+ /**
+ * The name of the operation used during serialization
+ *
+ * @return the operation serialized name
+ */
@NonNull
public String serializedName() {
return "VALUE_CHANGE";
@@ -85,6 +90,13 @@ public class ValueStringChangeActionOperation extends Operation implements Actio
context.overrideText(mTargetValueId, mValueId);
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param valueId the string id
+ * @param value the value to set (string id)`
+ */
public static void apply(@NonNull WireBuffer buffer, int valueId, int value) {
buffer.start(OP_CODE);
buffer.writeInt(valueId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java
index c3624e5b3d88..8c1ffbd2c500 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthInModifierOperation.java
@@ -19,47 +19,37 @@ import android.annotation.NonNull;
import com.android.internal.widget.remotecompose.core.Operation;
import com.android.internal.widget.remotecompose.core.Operations;
-import com.android.internal.widget.remotecompose.core.PaintContext;
import com.android.internal.widget.remotecompose.core.WireBuffer;
import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
-import com.android.internal.widget.remotecompose.core.operations.DrawBase2;
import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
import java.util.List;
/** Set the min / max width dimension on a component */
-public class WidthInModifierOperation extends DrawBase2 implements ModifierOperation {
+public class WidthInModifierOperation extends DimensionInModifierOperation {
private static final int OP_CODE = Operations.MODIFIER_WIDTH_IN;
public static final String CLASS_NAME = "WidthInModifierOperation";
- /**
- * Read this operation and add it to the list of operations
- *
- * @param buffer the buffer to read
- * @param operations the list of operations that will be added to
- */
- public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
- Maker m = WidthInModifierOperation::new;
- read(m, buffer, operations);
+ public WidthInModifierOperation(float min, float max) {
+ super(OP_CODE, min, max);
}
- /**
- * Returns the min value
- *
- * @return minimum value
- */
- public float getMin() {
- return mV1;
+ @Override
+ public void write(@NonNull WireBuffer buffer) {
+ apply(buffer, getMin(), getMax());
}
/**
- * Returns the max value
+ * Read this operation and add it to the list of operations
*
- * @return maximum value
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
*/
- public float getMax() {
- return mV2;
+ public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+ float v1 = buffer.readFloat();
+ float v2 = buffer.readFloat();
+ operations.add(new WidthInModifierOperation(v1, v2));
}
/**
@@ -81,11 +71,6 @@ public class WidthInModifierOperation extends DrawBase2 implements ModifierOpera
return CLASS_NAME;
}
- @Override
- protected void write(@NonNull WireBuffer buffer, float v1, float v2) {
- apply(buffer, v1, v2);
- }
-
/**
* Populate the documentation with a description of this operation
*
@@ -98,14 +83,6 @@ public class WidthInModifierOperation extends DrawBase2 implements ModifierOpera
.field(DocumentedOperation.FLOAT, "max", "The maximum width, -1 if not applied");
}
- public WidthInModifierOperation(float min, float max) {
- super(min, max);
- mName = CLASS_NAME;
- }
-
- @Override
- public void paint(@NonNull PaintContext context) {}
-
/**
* Writes out the WidthInModifier to the buffer
*
@@ -114,7 +91,9 @@ public class WidthInModifierOperation extends DrawBase2 implements ModifierOpera
* @param y1 start y of the DrawOval
*/
public static void apply(@NonNull WireBuffer buffer, float x1, float y1) {
- write(buffer, OP_CODE, x1, y1);
+ buffer.start(OP_CODE);
+ buffer.writeFloat(x1);
+ buffer.writeFloat(y1);
}
@Override
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
index 532027ab2087..687238e62bac 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java
@@ -52,6 +52,13 @@ public class WidthModifierOperation extends DimensionModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param type the type of dimension rule (DimensionModifierOperation.Type)
+ * @param value the value of the dimension
+ */
public static void apply(@NonNull WireBuffer buffer, int type, float value) {
buffer.start(OP_CODE);
buffer.writeInt(type);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java
index 35de33a9997a..52841a7e6779 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java
@@ -55,6 +55,12 @@ public class ZIndexModifierOperation extends DecoratorModifierOperation {
apply(buffer, mValue);
}
+ /**
+ * Serialize the string
+ *
+ * @param indent padding to display
+ * @param serializer append the string
+ */
// @Override
public void serializeToString(int indent, StringSerializer serializer) {
serializer.append(indent, "ZINDEX = [" + mValue + "]");
@@ -99,16 +105,33 @@ public class ZIndexModifierOperation extends DecoratorModifierOperation {
return OP_CODE;
}
+ /**
+ * Write the operation to the buffer
+ *
+ * @param buffer a WireBuffer
+ * @param value the z-index value
+ */
public static void apply(WireBuffer buffer, float value) {
buffer.start(OP_CODE);
buffer.writeFloat(value);
}
+ /**
+ * Read this operation and add it to the list of operations
+ *
+ * @param buffer the buffer to read
+ * @param operations the list of operations that will be added to
+ */
public static void read(WireBuffer buffer, List<Operation> operations) {
float value = buffer.readFloat();
operations.add(new ZIndexModifierOperation(value));
}
+ /**
+ * Populate the documentation with a description of this operation
+ *
+ * @param doc to append the description to.
+ */
public static void documentation(DocumentationBuilder doc) {
doc.operation("Modifier Operations", OP_CODE, CLASS_NAME)
.description("define the Z-Index Modifier")
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java
index 95434696abdc..4c7f503e0bf8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java
@@ -682,9 +682,9 @@ public class PaintBundle {
* @param radius Must be positive. The radius of the gradient.
* @param colors The sRGB colors distributed between the center and edge
* @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and <code>
- * 1.0f</code>. The relative position of each corresponding color in the colors array. If
- * <code>null</code>, colors are distributed evenly between the center and edge of the
- * circle.
+ * 1.0f</code>. The relative position of each corresponding color in the colors
+ * array. If <code>null</code>, colors are distributed evenly between the center and edge of
+ * the circle.
* @param tileMode The Shader tiling mode
*/
public void setRadialGradient(
@@ -808,7 +808,7 @@ public class PaintBundle {
}
/**
- * Set the color based the R,G,B,A values
+ * Set the color based the R,G,B,A values (Warning this does not support NaN ids)
*
* @param r red (0.0 to 1.0)
* @param g green (0.0 to 1.0)
@@ -816,7 +816,7 @@ public class PaintBundle {
* @param a alpha (0.0 to 1.0)
*/
public void setColor(float r, float g, float b, float a) {
- setColor((int) (r * 255), (int) (g * 255), (int) (b * 255), (int) (a * 255));
+ setColor(Utils.toARGB(a, r, g, b));
}
/**
@@ -897,6 +897,11 @@ public class PaintBundle {
mPos++;
}
+ /**
+ * set Filter Bitmap
+ *
+ * @param filter set to false to disable interpolation
+ */
public void setFilterBitmap(boolean filter) {
mArray[mPos] = FILTER_BITMAP | (filter ? (1 << 16) : 0);
mPos++;
@@ -944,6 +949,12 @@ public class PaintBundle {
}
}
+ /**
+ * Convert a blend mode integer as a string
+ *
+ * @param mode the blend mode
+ * @return the blend mode as a string
+ */
public static @NonNull String blendModeString(int mode) {
switch (mode) {
case PaintBundle.BLEND_MODE_CLEAR:
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/TextPaint.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/TextPaint.java
index ff6f45db5385..2812eed8a5ab 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/TextPaint.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/TextPaint.java
@@ -17,51 +17,250 @@ package com.android.internal.widget.remotecompose.core.operations.paint;
import android.annotation.NonNull;
+import java.util.Locale;
+
// TODO: this interface is unused. Delete it.
public interface TextPaint {
+
+ /**
+ * Helper to setColor(), that takes a,r,g,b and constructs the color int
+ *
+ * @param a The new alpha component (0..255) of the paint's color.
+ * @param r The new red component (0..255) of the paint's color.
+ * @param g The new green component (0..255) of the paint's color.
+ * @param b The new blue component (0..255) of the paint's color.
+ */
void setARGB(int a, int r, int g, int b);
+ /**
+ * Helper for setFlags(), setting or clearing the DITHER_FLAG bit Dithering affects how colors
+ * that are higher precision than the device are down-sampled. No dithering is generally faster,
+ * but higher precision colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
+ * distribute the error inherent in this process, to reduce the visual artifacts.
+ *
+ * @param dither true to set the dithering bit in flags, false to clear it
+ */
void setDither(boolean dither);
+ /**
+ * Set the paint's elegant height metrics flag. This setting selects font variants that have not
+ * been compacted to fit Latin-based vertical metrics, and also increases top and bottom bounds
+ * to provide more space.
+ *
+ * @param elegant set the paint's elegant metrics flag for drawing text.
+ */
void setElegantTextHeight(boolean elegant);
+ /**
+ * Set a end hyphen edit on the paint.
+ *
+ * <p>By setting end hyphen edit, the measurement and drawing is performed with modifying
+ * hyphenation at the end of line. For example, by passing character is appended at the end of
+ * line.
+ *
+ * <pre>
+ * <code>
+ * Paint paint = new Paint();
+ * paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
+ * paint.measureText("abc", 0, 3); // Returns the width of "abc-"
+ * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc-"
+ * </code>
+ * </pre>
+ *
+ * @param endHyphen a end hyphen edit value.
+ */
void setEndHyphenEdit(int endHyphen);
+ /**
+ * Helper for setFlags(), setting or clearing the FAKE_BOLD_TEXT_FLAG bit
+ *
+ * @param fakeBoldText true to set the fakeBoldText bit in the paint's flags, false to clear it.
+ */
void setFakeBoldText(boolean fakeBoldText);
+ /**
+ * Set the paint's flags. Use the Flag enum to specific flag values.
+ *
+ * @param flags The new flag bits for the paint
+ */
void setFlags(int flags);
+ /**
+ * Set font feature settings.
+ *
+ * <p>The format is the same as the CSS font-feature-settings attribute: <a
+ * href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
+ * https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop</a>
+ *
+ * @param settings the font feature settings string to use, may be null.
+ */
void setFontFeatureSettings(@NonNull String settings);
+ /**
+ * Set the paint's hinting mode. May be either
+ *
+ * @param mode The new hinting mode. (HINTING_OFF or HINTING_ON)
+ */
void setHinting(int mode);
+ /**
+ * Set the paint's letter-spacing for text. The default value is 0. The value is in 'EM' units.
+ * Typical values for slight expansion will be around 0.05. Negative values tighten text.
+ *
+ * @param letterSpacing set the paint's letter-spacing for drawing text.
+ */
void setLetterSpacing(float letterSpacing);
+ /**
+ * Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit
+ *
+ * @param linearText true to set the linearText bit in the paint's flags, false to clear it.
+ */
void setLinearText(boolean linearText);
+ /**
+ * This draws a shadow layer below the main layer, with the specified offset and color, and blur
+ * radius. If radius is 0, then the shadow layer is removed.
+ *
+ * <p>Can be used to create a blurred shadow underneath text. Support for use with other drawing
+ * operations is constrained to the software rendering pipeline.
+ *
+ * <p>The alpha of the shadow will be the paint's alpha if the shadow color is opaque, or the
+ * alpha from the shadow color if not.
+ *
+ * @param radius the radius of the shadows
+ * @param dx the x offset of the shadow
+ * @param dy the y offset of the shadow
+ * @param shadowColor the color of the shadow
+ */
void setShadowLayer(float radius, float dx, float dy, int shadowColor);
+ /**
+ * Set a start hyphen edit on the paint.
+ *
+ * <p>By setting start hyphen edit, the measurement and drawing is performed with modifying
+ * hyphenation at the start of line. For example, by passing character is appended at the start
+ * of line.
+ *
+ * <pre>
+ * <code>
+ * Paint paint = new Paint();
+ * paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
+ * paint.measureText("abc", 0, 3); // Returns the width of "-abc"
+ * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "-abc"
+ * </code>
+ * </pre>
+ *
+ * The default value is 0 which is equivalent to
+ *
+ * @param startHyphen a start hyphen edit value.
+ */
void setStartHyphenEdit(int startHyphen);
+ /**
+ * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
+ *
+ * @param strikeThruText true to set the strikeThruText bit in the paint's flags, false to clear
+ * it.
+ */
void setStrikeThruText(boolean strikeThruText);
+ /**
+ * Set the paint's Cap.
+ *
+ * @param cap set the paint's line cap style, used whenever the paint's style is Stroke or
+ * StrokeAndFill.
+ */
void setStrokeCap(int cap);
+ /**
+ * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit
+ *
+ * @param subpixelText true to set the subpixelText bit in the paint's flags, false to clear it.
+ */
void setSubpixelText(boolean subpixelText);
+ /**
+ * Set the paint's text alignment. This controls how the text is positioned relative to its
+ * origin. LEFT align means that all of the text will be drawn to the right of its origin (i.e.
+ * the origin specifies the LEFT edge of the text) and so on.
+ *
+ * @param align set the paint's Align value for drawing text.
+ */
void setTextAlign(int align);
+ /**
+ * Set the text locale list to a one-member list consisting of just the locale.
+ *
+ * @param locale the paint's locale value for drawing text, must not be null.
+ */
void setTextLocale(int locale);
+ /**
+ * Set the text locale list.
+ *
+ * <p>The text locale list affects how the text is drawn for some languages.
+ *
+ * <p>For example, if the locale list contains {@link Locale#CHINESE} or {@link Locale#CHINA},
+ * then the text renderer will prefer to draw text using a Chinese font. Likewise, if the locale
+ * list contains {@link Locale#JAPANESE} or {@link Locale#JAPAN}, then the text renderer will
+ * prefer to draw text using a Japanese font. If the locale list contains both, the order those
+ * locales appear in the list is considered for deciding the font.
+ *
+ * <p>This distinction is important because Chinese and Japanese text both use many of the same
+ * Unicode code points but their appearance is subtly different for each language.
+ *
+ * <p>By default, the text locale list is initialized to a one-member list just containing the
+ * system locales. This assumes that the text to be rendered will most likely be in the user's
+ * preferred language.
+ *
+ * <p>If the actual language or languages of the text is/are known, then they can be provided to
+ * the text renderer using this method. The text renderer may attempt to guess the language
+ * script based on the contents of the text to be drawn independent of the text locale here.
+ * Specifying the text locales just helps it do a better job in certain ambiguous cases.
+ *
+ * @param localesArray the paint's locale list for drawing text, must not be null or empty.
+ */
void setTextLocales(int localesArray);
+ /**
+ * Set the paint's horizontal scale factor for text. The default value is 1.0. Values > 1.0 will
+ * stretch the text wider. Values < 1.0 will stretch the text narrower.
+ *
+ * @param scaleX set the paint's scale in X for drawing/measuring text.
+ */
void setTextScaleX(float scaleX);
+ /**
+ * Set the paint's text size. This value must be > 0
+ *
+ * @param textSize set the paint's text size in pixel units.
+ */
void setTextSize(float textSize);
+ /**
+ * Set the paint's horizontal skew factor for text. The default value is 0. For approximating
+ * oblique text, use values around -0.25.
+ *
+ * @param skewX set the paint's skew factor in X for drawing text.
+ */
void setTextSkewX(float skewX);
+ /**
+ * Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit
+ *
+ * @param underlineText true to set the underlineText bit in the paint's flags, false to clear
+ * it.
+ */
void setUnderlineText(boolean underlineText);
+ /**
+ * Set the paint's extra word-spacing for text.
+ *
+ * <p>Increases the white space width between words with the given amount of pixels. The default
+ * value is 0.
+ *
+ * @param wordSpacing set the paint's extra word-spacing for drawing text in pixels.
+ */
void setWordSpacing(float wordSpacing);
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java
index b92f96f63eb9..704f6ce3447a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java
@@ -22,6 +22,14 @@ import android.annotation.Nullable;
* unavailable
*/
public interface CollectionsAccess {
+
+ /**
+ * Get the float value in the array at the given index
+ *
+ * @param id the id of the float array
+ * @param index the index of the value
+ * @return
+ */
float getFloatValue(int id, int index);
/**
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/DataMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/DataMap.java
index 07a3d8482db2..04beba3c4af8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/DataMap.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/DataMap.java
@@ -28,6 +28,12 @@ public class DataMap {
mIds = ids;
}
+ /**
+ * Return position for given string
+ *
+ * @param str string
+ * @return position associated with the string
+ */
public int getPos(@NonNull String str) {
for (int i = 0; i < mNames.length; i++) {
String name = mNames[i];
@@ -38,10 +44,22 @@ public class DataMap {
return -1;
}
+ /**
+ * Return type for given index
+ *
+ * @param pos index
+ * @return type at index
+ */
public byte getType(int pos) {
return mTypes[pos];
}
+ /**
+ * Return id for given index
+ *
+ * @param pos index
+ * @return id at index
+ */
public int getId(int pos) {
return mIds[pos];
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java
index 98ee91b370e0..93af8bcef206 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/ImageScaling.java
@@ -76,6 +76,20 @@ public class ImageScaling {
adjustDrawToType();
}
+ /**
+ * Setup the ImageScaling
+ *
+ * @param srcLeft src left
+ * @param srcTop src top
+ * @param srcRight src right
+ * @param srcBottom src bottom
+ * @param dstLeft destination left
+ * @param dstTop destination top
+ * @param dstRight destination right
+ * @param dstBottom destination bottom
+ * @param type type of scaling
+ * @param scale scale factor
+ */
public void setup(
float srcLeft,
float srcTop,
@@ -215,6 +229,12 @@ public class ImageScaling {
}
}
+ /**
+ * Utility to map a string to the given type
+ *
+ * @param type
+ * @return
+ */
@NonNull
public static String typeToString(int type) {
String[] typeString = {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java
index b9aa88146f2a..257eb0645938 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntMap.java
@@ -39,12 +39,20 @@ public class IntMap<T> {
}
}
+ /** Clear the map */
public void clear() {
Arrays.fill(mKeys, NOT_PRESENT);
mValues.clear();
mSize = 0;
}
+ /**
+ * Insert the value into the map with the given key
+ *
+ * @param key
+ * @param value
+ * @return
+ */
@Nullable
public T put(int key, @NonNull T value) {
if (key == NOT_PRESENT) throw new IllegalArgumentException("Key cannot be NOT_PRESENT");
@@ -54,6 +62,12 @@ public class IntMap<T> {
return insert(key, value);
}
+ /**
+ * Return the value associated with the given key
+ *
+ * @param key
+ * @return
+ */
@Nullable
public T get(int key) {
int index = findKey(key);
@@ -62,6 +76,11 @@ public class IntMap<T> {
} else return mValues.get(index);
}
+ /**
+ * Return the size of the map
+ *
+ * @return
+ */
public int size() {
return mSize;
}
@@ -117,6 +136,12 @@ public class IntMap<T> {
}
}
+ /**
+ * Remote the key from the map
+ *
+ * @param key
+ * @return
+ */
@Nullable
public T remove(int key) {
int index = hash(key) % mKeys.length;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java
index 0616cc7306f5..1f98f62a20b3 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/NanMap.java
@@ -41,18 +41,42 @@ public class NanMap {
public static final float CLOSE_NAN = Utils.asNan(CLOSE);
public static final float DONE_NAN = Utils.asNan(DONE);
+ /**
+ * Returns true if the float id is a system variable
+ *
+ * @param value the id encoded as float NaN
+ * @return
+ */
public static boolean isSystemVariable(float value) {
return (fromNaN(value) >> 20) == 0;
}
+ /**
+ * Returns true if the float id is a normal variable
+ *
+ * @param value the id encoded as float NaN
+ * @return
+ */
public static boolean isNormalVariable(float value) {
return (fromNaN(value) >> 20) == 1;
}
+ /**
+ * Returns true if the float id is a data variable
+ *
+ * @param value the id encoded as float NaN
+ * @return
+ */
public static boolean isDataVariable(float value) {
return (fromNaN(value) >> 20) == 2;
}
+ /**
+ * Returns true if the float id is an operation variable
+ *
+ * @param value the id encoded as float NaN
+ * @return
+ */
public static boolean isOperationVariable(float value) {
return (fromNaN(value) >> 20) == 3;
}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java b/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java
index cc6c2a6ac7a9..928e9ea1a280 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java
@@ -134,6 +134,12 @@ public interface AccessibleComponent extends AccessibilitySemantics {
return mDescription;
}
+ /**
+ * Map int value to Role enum value
+ *
+ * @param i int value
+ * @return corresponding enum value
+ */
public static Role fromInt(int i) {
if (i < UNKNOWN.ordinal()) {
return Role.values()[i];
diff --git a/core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java b/core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java
new file mode 100644
index 000000000000..2be8057ce097
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/serialize/MapSerializer.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core.serialize;
+
+import android.annotation.Nullable;
+
+import java.util.List;
+import java.util.Map;
+
+/** Represents a serializer for a map */
+public interface MapSerializer {
+
+ /**
+ * Add a list entry to this map. The List values can be any primitive, List, Map, or
+ * Serializable
+ *
+ * @param key The key
+ * @param value The list
+ */
+ <T> void add(String key, @Nullable List<T> value);
+
+ /**
+ * Add a map entry to this map. The map values can be any primitive, List, Map, or Serializable
+ *
+ * @param key The key
+ * @param value The list
+ */
+ <T> void add(String key, @Nullable Map<String, T> value);
+
+ /**
+ * Adds any Serializable type to this map
+ *
+ * @param key The key
+ * @param value The Serializable
+ */
+ void add(String key, @Nullable Serializable value);
+
+ /**
+ * Adds a String entry
+ *
+ * @param key The key
+ * @param value The String
+ */
+ void add(String key, @Nullable String value);
+
+ /**
+ * Adds a Byte entry
+ *
+ * @param key The key
+ * @param value The Byte
+ */
+ void add(String key, @Nullable Byte value);
+
+ /**
+ * Adds a Short entry
+ *
+ * @param key The key
+ * @param value The Short
+ */
+ void add(String key, @Nullable Short value);
+
+ /**
+ * Adds an Integer entry
+ *
+ * @param key The key
+ * @param value The Integer
+ */
+ void add(String key, @Nullable Integer value);
+
+ /**
+ * Adds a Long entry
+ *
+ * @param key The key
+ * @param value The Long
+ */
+ void add(String key, @Nullable Long value);
+
+ /**
+ * Adds a Float entry
+ *
+ * @param key The key
+ * @param value The Float
+ */
+ void add(String key, @Nullable Float value);
+
+ /**
+ * Adds a Double entry
+ *
+ * @param key The key
+ * @param value The Double
+ */
+ void add(String key, @Nullable Double value);
+
+ /**
+ * Adds a Boolean entry
+ *
+ * @param key The key
+ * @param value The Boolean
+ */
+ void add(String key, @Nullable Boolean value);
+
+ /**
+ * Adds a Enum entry
+ *
+ * @param key The key
+ * @param value The Enum
+ */
+ <T extends Enum<T>> void add(String key, @Nullable Enum<T> value);
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/serialize/Serializable.java b/core/java/com/android/internal/widget/remotecompose/core/serialize/Serializable.java
new file mode 100644
index 000000000000..820cdccfeabb
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/serialize/Serializable.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.widget.remotecompose.core.serialize;
+
+/** Implementation for any class that wants to serialize itself */
+public interface Serializable {
+
+ /**
+ * Called when this class is to be serialized
+ *
+ * @param serializer Interface to the serializer
+ */
+ void serialize(MapSerializer serializer);
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java
index b17e3dc82d50..77f4b6a83eef 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java
@@ -39,12 +39,13 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.remotecompose.accessibility.RemoteComposeTouchHelper;
import com.android.internal.widget.remotecompose.core.CoreDocument;
import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.RemoteContextAware;
import com.android.internal.widget.remotecompose.core.operations.NamedVariable;
import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior;
import com.android.internal.widget.remotecompose.player.platform.RemoteComposeCanvas;
/** A view to to display and play RemoteCompose documents */
-public class RemoteComposePlayer extends FrameLayout {
+public class RemoteComposePlayer extends FrameLayout implements RemoteContextAware {
private RemoteComposeCanvas mInner;
private static final int MAX_SUPPORTED_MAJOR_VERSION = MAJOR_VERSION;
@@ -65,6 +66,11 @@ public class RemoteComposePlayer extends FrameLayout {
init(context, attrs, defStyleAttr);
}
+ @Override
+ public RemoteContext getRemoteContext() {
+ return mInner.getRemoteContext();
+ }
+
/**
* @inheritDoc
*/
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java
index 9d385ddafe19..14349b028819 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java
@@ -185,7 +185,7 @@ public class AndroidRemoteContext extends RemoteContext {
@Override
public void runAction(int id, @NonNull String metadata) {
- mDocument.performClick(id);
+ mDocument.performClick(this, id);
}
@Override
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
index 334ba62636ff..f76794fc0372 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
@@ -147,7 +147,7 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta
param.leftMargin = (int) area.getLeft();
param.topMargin = (int) area.getTop();
viewArea.setOnClickListener(
- view1 -> mDocument.getDocument().performClick(area.getId()));
+ view1 -> mDocument.getDocument().performClick(mARContext, area.getId()));
addView(viewArea, param);
}
if (!clickAreas.isEmpty()) {
@@ -303,6 +303,10 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta
mARContext.setUseChoreographer(value);
}
+ public RemoteContext getRemoteContext() {
+ return mARContext;
+ }
+
public interface ClickCallbacks {
void click(int id, String metadata);
}
diff --git a/core/jni/android_app_PropertyInvalidatedCache.h b/core/jni/android_app_PropertyInvalidatedCache.h
index 00aa281b572f..54a4ac65fce2 100644
--- a/core/jni/android_app_PropertyInvalidatedCache.h
+++ b/core/jni/android_app_PropertyInvalidatedCache.h
@@ -147,10 +147,12 @@ template<int maxNonce, size_t maxByte> class CacheNonce : public NonceStore {
}
};
-// The CacheNonce for system server holds 64 nonces with a string block of 8192 bytes. This is
-// more than enough for system_server PropertyInvalidatedCache support. The configuration
-// values are not defined as visible constants. Clients should use the accessors on the
-// SystemCacheNonce instance if they need the sizing parameters.
-typedef CacheNonce</* max nonce */ 64, /* byte block size */ 8192> SystemCacheNonce;
+// The CacheNonce for system server. The configuration values are not defined as visible
+// constants. Clients should use the accessors on the SystemCacheNonce instance if they need
+// the sizing parameters.
+
+// LINT.IfChange(system_nonce_config)
+typedef CacheNonce</* max nonce */ 128, /* byte block size */ 8192> SystemCacheNonce;
+// LINT.ThenChange(/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java:system_nonce_config)
} // namespace android.app.PropertyInvalidatedCache
diff --git a/core/jni/android_hardware_display_DisplayTopology.cpp b/core/jni/android_hardware_display_DisplayTopology.cpp
index d9e802de81e0..a16f3c3c20b8 100644
--- a/core/jni/android_hardware_display_DisplayTopology.cpp
+++ b/core/jni/android_hardware_display_DisplayTopology.cpp
@@ -35,6 +35,7 @@ static struct {
static struct {
jclass clazz;
jfieldID displayId;
+ jfieldID density;
jfieldID adjacentDisplays;
} gDisplayTopologyGraphNodeClassInfo;
@@ -42,7 +43,7 @@ static struct {
jclass clazz;
jfieldID displayId;
jfieldID position;
- jfieldID offsetPx;
+ jfieldID offsetDp;
} gDisplayTopologyGraphAdjacentDisplayClassInfo;
// ----------------------------------------------------------------------------
@@ -55,19 +56,23 @@ status_t android_hardware_display_DisplayTopologyAdjacentDisplay_toNative(
adjacentDisplay->position = static_cast<DisplayTopologyPosition>(
env->GetIntField(adjacentDisplayObj,
gDisplayTopologyGraphAdjacentDisplayClassInfo.position));
- adjacentDisplay->offsetPx =
+ adjacentDisplay->offsetDp =
env->GetFloatField(adjacentDisplayObj,
- gDisplayTopologyGraphAdjacentDisplayClassInfo.offsetPx);
+ gDisplayTopologyGraphAdjacentDisplayClassInfo.offsetDp);
return OK;
}
status_t android_hardware_display_DisplayTopologyGraphNode_toNative(
JNIEnv* env, jobject nodeObj,
std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>&
- graph) {
+ graph,
+ std::unordered_map<ui::LogicalDisplayId, int>& displaysDensity) {
ui::LogicalDisplayId displayId = ui::LogicalDisplayId{
env->GetIntField(nodeObj, gDisplayTopologyGraphNodeClassInfo.displayId)};
+ displaysDensity[displayId] =
+ env->GetIntField(nodeObj, gDisplayTopologyGraphNodeClassInfo.density);
+
jobjectArray adjacentDisplaysArray = static_cast<jobjectArray>(
env->GetObjectField(nodeObj, gDisplayTopologyGraphNodeClassInfo.adjacentDisplays));
@@ -109,7 +114,8 @@ DisplayTopologyGraph android_hardware_display_DisplayTopologyGraph_toNative(JNIE
}
android_hardware_display_DisplayTopologyGraphNode_toNative(env, nodeObj.get(),
- topology.graph);
+ topology.graph,
+ topology.displaysDensity);
}
}
return topology;
@@ -132,6 +138,8 @@ int register_android_hardware_display_DisplayTopology(JNIEnv* env) {
gDisplayTopologyGraphNodeClassInfo.clazz = MakeGlobalRefOrDie(env, displayNodeClazz);
gDisplayTopologyGraphNodeClassInfo.displayId =
GetFieldIDOrDie(env, gDisplayTopologyGraphNodeClassInfo.clazz, "displayId", "I");
+ gDisplayTopologyGraphNodeClassInfo.density =
+ GetFieldIDOrDie(env, gDisplayTopologyGraphNodeClassInfo.clazz, "density", "I");
gDisplayTopologyGraphNodeClassInfo.adjacentDisplays =
GetFieldIDOrDie(env, gDisplayTopologyGraphNodeClassInfo.clazz, "adjacentDisplays",
"[Landroid/hardware/display/DisplayTopologyGraph$AdjacentDisplay;");
@@ -146,8 +154,8 @@ int register_android_hardware_display_DisplayTopology(JNIEnv* env) {
gDisplayTopologyGraphAdjacentDisplayClassInfo.position =
GetFieldIDOrDie(env, gDisplayTopologyGraphAdjacentDisplayClassInfo.clazz, "position",
"I");
- gDisplayTopologyGraphAdjacentDisplayClassInfo.offsetPx =
- GetFieldIDOrDie(env, gDisplayTopologyGraphAdjacentDisplayClassInfo.clazz, "offsetPx",
+ gDisplayTopologyGraphAdjacentDisplayClassInfo.offsetDp =
+ GetFieldIDOrDie(env, gDisplayTopologyGraphAdjacentDisplayClassInfo.clazz, "offsetDp",
"F");
return 0;
}
diff --git a/core/proto/android/service/appwidget.proto b/core/proto/android/service/appwidget.proto
index fb907196bfc7..5dc90e02faf5 100644
--- a/core/proto/android/service/appwidget.proto
+++ b/core/proto/android/service/appwidget.proto
@@ -39,6 +39,7 @@ message WidgetProto {
optional int32 maxWidth = 8;
optional int32 maxHeight = 9;
optional bool restoreCompleted = 10;
+ optional int32 views_bitmap_memory = 11;
}
// represents a set of widget previews for a particular provider
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 1fdbe8c35f3e..68712916e1df 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1069,19 +1069,19 @@
<string name="lockscreen_access_pattern_cell_added_verbose" msgid="2931364927622563465">"تمت إضافة الخلية <xliff:g id="CELL_INDEX">%1$s</xliff:g>"</string>
<string name="lockscreen_access_pattern_detected" msgid="3931150554035194012">"اكتمل النمط"</string>
<string name="lockscreen_access_pattern_area" msgid="1288780416685002841">"منطقة النقش."</string>
- <string name="keyguard_accessibility_widget_changed" msgid="7298011259508200234">"‏%1$s. الأداة %2$d من %3$d."</string>
- <string name="keyguard_accessibility_add_widget" msgid="8245795023551343672">"إضافة أداة."</string>
+ <string name="keyguard_accessibility_widget_changed" msgid="7298011259508200234">"‏%1$s. التطبيق المصغَّر %2$d من %3$d."</string>
+ <string name="keyguard_accessibility_add_widget" msgid="8245795023551343672">"إضافة تطبيق مصغَّر."</string>
<string name="keyguard_accessibility_widget_empty_slot" msgid="544239307077644480">"فارغة"</string>
<string name="keyguard_accessibility_unlock_area_expanded" msgid="7768634718706488951">"تم توسيع منطقة فتح القفل."</string>
<string name="keyguard_accessibility_unlock_area_collapsed" msgid="4729922043778400434">"تم تصغير منطقة فتح القفل."</string>
- <string name="keyguard_accessibility_widget" msgid="6776892679715699875">"أداة <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+ <string name="keyguard_accessibility_widget" msgid="6776892679715699875">"التطبيق المصغَّر <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
<string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"محدد المستخدم"</string>
<string name="keyguard_accessibility_status" msgid="6792745049712397237">"الحالة"</string>
<string name="keyguard_accessibility_camera" msgid="7862557559464986528">"الكاميرا"</string>
<string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"أدوات التحكم في الوسائط"</string>
- <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"بدأت إعادة ترتيب الأدوات."</string>
- <string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"انتهت إعادة ترتيب الأدوات."</string>
- <string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"تم حذف أداة <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
+ <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"بدأت إعادة ترتيب التطبيقات المصغَّرة."</string>
+ <string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"انتهت إعادة ترتيب التطبيقات المصغَّرة."</string>
+ <string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"تم حذف التطبيق المصغَّر <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"توسيع منطقة فتح القفل."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"فتح القفل باستخدام التمرير."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"فتح القفل باستخدام النقش."</string>
@@ -1536,7 +1536,7 @@
<string name="permlab_queryAllPackages" msgid="2928450604653281650">"البحث في كل الحِزم"</string>
<string name="permdesc_queryAllPackages" msgid="5339069855520996010">"يسمح هذا الإذن للتطبيق بعرض كل الحِزم المثبّتة."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"اضغط مرتين للتحكم في التكبير أو التصغير"</string>
- <string name="gadget_host_error_inflating" msgid="2449961590495198720">"تعذرت إضافة أداة."</string>
+ <string name="gadget_host_error_inflating" msgid="2449961590495198720">"تعذرت إضافة تطبيق مصغَّر."</string>
<string name="ime_action_go" msgid="5536744546326495436">"تنفيذ"</string>
<string name="ime_action_search" msgid="4501435960587287668">"بحث"</string>
<string name="ime_action_send" msgid="8456843745664334138">"إرسال"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index d775f448d2ce..6f677e3ad84b 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -2219,7 +2219,7 @@
<string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth permanecerá activado mentres se utilice o modo avión"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"Cargando"</string>
<string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # ficheiro}other{{file_name} + # ficheiros}}"</string>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Non hai recomendacións de persoas coas que compartir contido"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Non hai recomendacións de persoas coas que compartir isto"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de aplicacións"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Esta aplicación non está autorizada a realizar gravacións, pero podería capturar audio a través deste dispositivo USB."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Inicio"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index ffca8688ac51..cbc989ef58f4 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -2110,7 +2110,7 @@
<string name="time_picker_minute_label" msgid="8307452311269824553">"דקה"</string>
<string name="time_picker_header_text" msgid="9073802285051516688">"הגדרת שעה"</string>
<string name="time_picker_input_error" msgid="8386271930742451034">"יש להזין שעה חוקית"</string>
- <string name="time_picker_prompt_label" msgid="303588544656363889">"מהי השעה הנכונה"</string>
+ <string name="time_picker_prompt_label" msgid="303588544656363889">"צריך להקליד את השעה הרצויה"</string>
<string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"מעבר לשיטת קלט טקסט כדי להזין את השעה"</string>
<string name="time_picker_radial_mode_description" msgid="1222342577115016953">"מעבר למצב שעון לצורך הזנת השעה"</string>
<string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"אפשרויות מילוי אוטומטי"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 774e4edc1cd6..f2de857dee11 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -147,7 +147,7 @@
<string name="wfcSpnFormat_wifi_call" msgid="434016592539090004">"Повик преку WiFi"</string>
<string name="wifi_calling_off_summary" msgid="5626710010766902560">"Исклучено"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Повикувај преку Wi-Fi"</string>
- <string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Повикувај преку мобилна мрежа"</string>
+ <string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Повикувајте преку мобилна мрежа"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Само Wi-Fi"</string>
<!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
<skip />
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 9dbfc1e58e89..2c4b9f45d5e8 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -2109,7 +2109,7 @@
<string name="time_picker_minute_label" msgid="8307452311269824553">"минут"</string>
<string name="time_picker_header_text" msgid="9073802285051516688">"Цаг тохируулах"</string>
<string name="time_picker_input_error" msgid="8386271930742451034">"Цагийг зөв оруулна уу"</string>
- <string name="time_picker_prompt_label" msgid="303588544656363889">"Хугацааг бичнэ үү"</string>
+ <string name="time_picker_prompt_label" msgid="303588544656363889">"Цагийг бичиж оруулна уу"</string>
<string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"Цагийг оруулахын тулд текст оруулах горимд шилжүүлнэ үү."</string>
<string name="time_picker_radial_mode_description" msgid="1222342577115016953">"Цагийг оруулахын тулд цагийн горимд шилжүүлнэ үү."</string>
<string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"Автоматаар бөглөх хэсгийн сонголт"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 750988a242b7..63b017a766ed 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1206,7 +1206,7 @@
<string name="delete" msgid="1514113991712129054">"हटवा"</string>
<string name="copyUrl" msgid="6229645005987260230">"URL कॉपी करा"</string>
<string name="selectTextMode" msgid="3225108910999318778">"मजकूर निवडा"</string>
- <string name="undo" msgid="3175318090002654673">"पूर्ववत करा"</string>
+ <string name="undo" msgid="3175318090002654673">"पहिल्यासारखे करा"</string>
<string name="redo" msgid="7231448494008532233">"पुन्हा करा"</string>
<string name="autofill" msgid="511224882647795296">"स्वयं-भरण"</string>
<string name="textSelectionCABTitle" msgid="5151441579532476940">"मजकूर निवड"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index f7a25e9288b6..2776e1ce0404 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -2469,7 +2469,7 @@
<string name="satellite_manual_selection_state_popup_title" msgid="8545991934926661974">"Vklopite »Samodejno izberi omrežje«"</string>
<string name="satellite_manual_selection_state_popup_message" msgid="1928101658551382450">"V nastavitvah vklopite možnost »Samodejno izberi omrežje«, da bo telefon lahko našel omrežje, ki deluje s satelitsko povezavo"</string>
<string name="satellite_manual_selection_state_popup_ok" msgid="2459664752624985095">"Vklopi"</string>
- <string name="satellite_manual_selection_state_popup_cancel" msgid="973605633339469252">"Nazaj"</string>
+ <string name="satellite_manual_selection_state_popup_cancel" msgid="973605633339469252">"Pomik nazaj"</string>
<string name="unarchival_session_app_label" msgid="6811856981546348205">"V teku …"</string>
<string name="satellite_sos_available_notification_title" msgid="5396708154268096124">"SOS prek satelita je zdaj na voljo"</string>
<string name="satellite_sos_available_notification_summary" msgid="1727088812951848330">"Reševalnim službam lahko pošljete sporočilo, če ni povezave z mobilnim omrežjem ali omrežjem Wi-Fi. Google Sporočila morajo biti privzeta aplikacija za sporočanje."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 38f9175cc919..8c5acd45fd12 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -2459,7 +2459,7 @@
<string name="screen_not_shared_sensitive_content" msgid="7058419185079565001">"பாதுகாப்பிற்காக, திரைப் பகிர்வில் இருந்து ஆப்ஸ் உள்ளடக்கம் மறைக்கப்பட்டுள்ளது"</string>
<string name="satellite_notification_title" msgid="4026338973463121526">"சாட்டிலைட்டுடன் தானாக இணைக்கப்பட்டது"</string>
<string name="satellite_notification_summary" msgid="5207364139430767162">"மொபைல்/வைஃபை நெட்வொர்க் இல்லாமல் நீங்கள் மெசேஜ்களை அனுப்பலாம் பெறலாம்"</string>
- <string name="satellite_notification_summary_with_data" msgid="6486843676720429049">"சாட்டிலைட் மூலம் நீங்கள் மெசேஜ்களை அனுப்பலாம் பெறலாம், வரம்பிடப்பட்ட டேட்டாவைப் பயன்படுத்தலாம்"</string>
+ <string name="satellite_notification_summary_with_data" msgid="6486843676720429049">"சாட்டிலைட் மூலம் நீங்கள் மெசேஜ் அனுப்பலாம் பெறலாம், குறிப்பிட்ட அளவு டேட்டாவைப் பயன்படுத்தலாம்"</string>
<string name="satellite_notification_manual_title" msgid="1097504441849466279">"சாட்டிலைட் மெசேஜிங்கைப் பயன்படுத்தவா?"</string>
<string name="satellite_notification_manual_summary" msgid="901206289846283445">"மொபைல்/வைஃபை நெட்வொர்க் இல்லாமல் மெசேஜ்களை அனுப்பலாம், பெறலாம்"</string>
<string name="satellite_notification_open_message" msgid="4149234979688273729">"Messages ஆப்ஸைத் திறக்கவும்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 2a99f758daf7..8333b0bafc02 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -2109,7 +2109,7 @@
<string name="time_picker_minute_label" msgid="8307452311269824553">"నిమిషం"</string>
<string name="time_picker_header_text" msgid="9073802285051516688">"సమయాన్ని సెట్ చేయండి"</string>
<string name="time_picker_input_error" msgid="8386271930742451034">"చెల్లుబాటు అయ్యే సమయాన్ని నమోదు చేయండి"</string>
- <string name="time_picker_prompt_label" msgid="303588544656363889">"సమయంలో టైప్ చేయండి"</string>
+ <string name="time_picker_prompt_label" msgid="303588544656363889">"టైమ్ ఎంట‌ర్ చేయండి"</string>
<string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"సమయాన్ని నమోదు చేయడం కోసం వచన నమోదు మోడ్‌కి మారండి."</string>
<string name="time_picker_radial_mode_description" msgid="1222342577115016953">"సమయాన్ని నమోదు చేయడం కోసం గడియారం మోడ్‌కు మారండి."</string>
<string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"స్వీయ పూరింపు ఎంపికలు"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c5cad4bc9503..7888f4749e25 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -620,8 +620,8 @@
<string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"允许该应用向附近的 WLAN 设备进行广播、连接到这些设备以及确定这些设备的相对位置"</string>
<string name="permlab_ranging" msgid="2854543350668593390">"确定附近的设备之间的相对位置"</string>
<string name="permdesc_ranging" msgid="6703905535621521710">"允许应用确定附近的设备之间的相对位置"</string>
- <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"首选 NFC 付款服务信息"</string>
- <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允许应用获取首选 NFC 付款服务信息,例如注册的应用标识符和路线目的地。"</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"首选 NFC 支付服务信息"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允许应用获取首选 NFC 支付服务信息,例如注册的应用标识符和路线目的地。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距离通信"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"允许应用与近距离无线通信(NFC)标签、卡和读取器通信。"</string>
<string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"安全元件事务事件"</string>
diff --git a/core/tests/coretests/src/android/app/NotificationManagerTest.java b/core/tests/coretests/src/android/app/NotificationManagerTest.java
index 41432294b3c2..9b97c8feaf12 100644
--- a/core/tests/coretests/src/android/app/NotificationManagerTest.java
+++ b/core/tests/coretests/src/android/app/NotificationManagerTest.java
@@ -19,7 +19,6 @@ package android.app;
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;
@@ -304,9 +303,8 @@ public class NotificationManagerTest {
// It doesn't matter what the returned contents are, as long as we return a channel.
// This setup must set up getNotificationChannels(), as that's the method called.
- when(mNotificationManager.mBackendService.getOrCreateNotificationChannels(any(), any(),
- anyInt(), anyBoolean())).thenReturn(
- new ParceledListSlice<>(List.of(exampleChannel())));
+ when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(),
+ anyInt())).thenReturn(new ParceledListSlice<>(List.of(exampleChannel())));
// ask for the same channel 100 times without invalidating the cache
for (int i = 0; i < 100; i++) {
@@ -318,7 +316,7 @@ public class NotificationManagerTest {
NotificationChannel unused = mNotificationManager.getNotificationChannel("id");
verify(mNotificationManager.mBackendService, times(2))
- .getOrCreateNotificationChannels(any(), any(), anyInt(), anyBoolean());
+ .getNotificationChannels(any(), any(), anyInt());
}
@Test
@@ -331,24 +329,23 @@ public class NotificationManagerTest {
NotificationChannel c2 = new NotificationChannel("id2", "name2",
NotificationManager.IMPORTANCE_NONE);
- when(mNotificationManager.mBackendService.getOrCreateNotificationChannels(any(), any(),
- anyInt(), anyBoolean())).thenReturn(new ParceledListSlice<>(List.of(c1, c2)));
+ when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(),
+ anyInt())).thenReturn(new ParceledListSlice<>(List.of(c1, c2)));
assertThat(mNotificationManager.getNotificationChannel("id1")).isEqualTo(c1);
assertThat(mNotificationManager.getNotificationChannel("id2")).isEqualTo(c2);
assertThat(mNotificationManager.getNotificationChannel("id3")).isNull();
verify(mNotificationManager.mBackendService, times(1))
- .getOrCreateNotificationChannels(any(), any(), anyInt(), anyBoolean());
+ .getNotificationChannels(any(), any(), anyInt());
}
@Test
@EnableFlags(Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS)
public void getNotificationChannels_cachedUntilInvalidated() throws Exception {
NotificationManager.invalidateNotificationChannelCache();
- when(mNotificationManager.mBackendService.getOrCreateNotificationChannels(any(), any(),
- anyInt(), anyBoolean())).thenReturn(
- new ParceledListSlice<>(List.of(exampleChannel())));
+ when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(),
+ anyInt())).thenReturn(new ParceledListSlice<>(List.of(exampleChannel())));
// ask for channels 100 times without invalidating the cache
for (int i = 0; i < 100; i++) {
@@ -360,7 +357,7 @@ public class NotificationManagerTest {
List<NotificationChannel> res = mNotificationManager.getNotificationChannels();
verify(mNotificationManager.mBackendService, times(2))
- .getOrCreateNotificationChannels(any(), any(), anyInt(), anyBoolean());
+ .getNotificationChannels(any(), any(), anyInt());
assertThat(res).containsExactlyElementsIn(List.of(exampleChannel()));
}
@@ -378,9 +375,8 @@ public class NotificationManagerTest {
NotificationChannel c2 = new NotificationChannel("other", "name2",
NotificationManager.IMPORTANCE_DEFAULT);
- when(mNotificationManager.mBackendService.getOrCreateNotificationChannels(any(), any(),
- anyInt(), anyBoolean())).thenReturn(
- new ParceledListSlice<>(List.of(c1, conv1, c2)));
+ when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(),
+ anyInt())).thenReturn(new ParceledListSlice<>(List.of(c1, conv1, c2)));
// Lookup for channel c1 and c2: returned as expected
assertThat(mNotificationManager.getNotificationChannel("id")).isEqualTo(c1);
@@ -397,9 +393,9 @@ public class NotificationManagerTest {
// Lookup of a nonexistent channel is null
assertThat(mNotificationManager.getNotificationChannel("id3")).isNull();
- // All of that should have been one call to getOrCreateNotificationChannels()
+ // All of that should have been one call to getNotificationChannels()
verify(mNotificationManager.mBackendService, times(1))
- .getOrCreateNotificationChannels(any(), any(), anyInt(), anyBoolean());
+ .getNotificationChannels(any(), any(), anyInt());
}
@Test
@@ -419,12 +415,12 @@ public class NotificationManagerTest {
NotificationChannel channel3 = channel1.copy();
channel3.setName("name3");
- when(mNotificationManager.mBackendService.getOrCreateNotificationChannels(any(), eq(pkg1),
- eq(userId), anyBoolean())).thenReturn(new ParceledListSlice<>(List.of(channel1)));
- when(mNotificationManager.mBackendService.getOrCreateNotificationChannels(any(), eq(pkg2),
- eq(userId), anyBoolean())).thenReturn(new ParceledListSlice<>(List.of(channel2)));
- when(mNotificationManager.mBackendService.getOrCreateNotificationChannels(any(), eq(pkg1),
- eq(userId1), anyBoolean())).thenReturn(new ParceledListSlice<>(List.of(channel3)));
+ when(mNotificationManager.mBackendService.getNotificationChannels(any(), eq(pkg1),
+ eq(userId))).thenReturn(new ParceledListSlice<>(List.of(channel1)));
+ when(mNotificationManager.mBackendService.getNotificationChannels(any(), eq(pkg2),
+ eq(userId))).thenReturn(new ParceledListSlice<>(List.of(channel2)));
+ when(mNotificationManager.mBackendService.getNotificationChannels(any(), eq(pkg1),
+ eq(userId1))).thenReturn(new ParceledListSlice<>(List.of(channel3)));
// set our context to pretend to be from package 1 and userId 0
mContext.setParameters(pkg1, pkg1, userId);
@@ -440,7 +436,7 @@ public class NotificationManagerTest {
// Those should have been three different calls
verify(mNotificationManager.mBackendService, times(3))
- .getOrCreateNotificationChannels(any(), any(), anyInt(), anyBoolean());
+ .getNotificationChannels(any(), any(), anyInt());
}
@Test
diff --git a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
index 5da2564e5b7f..ac78e87aa60d 100644
--- a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
+++ b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
@@ -37,8 +37,10 @@ import android.app.PropertyInvalidatedCache.Args;
import android.app.PropertyInvalidatedCache.NonceWatcher;
import android.app.PropertyInvalidatedCache.NonceStore;
import android.os.Binder;
+import android.util.Log;
import com.android.internal.os.ApplicationSharedMemory;
+import android.platform.test.annotations.DisabledOnRavenwood;
import android.platform.test.annotations.IgnoreUnderRavenwood;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
@@ -410,8 +412,7 @@ public class PropertyInvalidatedCacheTests {
// Verify that invalidating the cache from an app process would fail due to lack of permissions.
@Test
- @android.platform.test.annotations.DisabledOnRavenwood(
- reason = "SystemProperties doesn't have permission check")
+ @DisabledOnRavenwood(reason = "SystemProperties doesn't have permission check")
public void testPermissionFailure() {
// Create a cache that will write a system nonce.
TestCache sysCache = new TestCache(MODULE_SYSTEM, "mode1");
@@ -556,8 +557,7 @@ public class PropertyInvalidatedCacheTests {
// storing nonces in shared memory.
@RequiresFlagsEnabled(FLAG_APPLICATION_SHARED_MEMORY_ENABLED)
@Test
- @android.platform.test.annotations.DisabledOnRavenwood(
- reason = "PIC doesn't use SharedMemory on Ravenwood")
+ @DisabledOnRavenwood(reason = "PIC doesn't use SharedMemory on Ravenwood")
public void testSharedMemoryStorage() {
// Fetch a shared memory instance for testing.
ApplicationSharedMemory shmem = ApplicationSharedMemory.create();
@@ -602,6 +602,49 @@ public class PropertyInvalidatedCacheTests {
shmem.close();
}
+ // Verify that the configured number of nonce slots is actually available. This test
+ // hard-codes the configured number of slots, which means that this test must be changed
+ // whenever the shared memory configuration changes.
+ @RequiresFlagsEnabled(FLAG_APPLICATION_SHARED_MEMORY_ENABLED)
+ @Test
+ @DisabledOnRavenwood(reason = "PIC doesn't use SharedMemory on Ravenwood")
+ public void testSharedMemoryNonceConfig() {
+ // The two configured constants. These are private to this method since they are only
+ // used here.
+ // LINT.IfChange(system_nonce_config)
+ final int maxNonce = 128;
+ final int maxByte = 8192;
+ // LINT.ThenChange(/core/jni/android_app_PropertyInvalidatedCache.h:system_nonce_config)
+
+ // Fetch a shared memory instance for testing.
+ ApplicationSharedMemory shmem = ApplicationSharedMemory.create();
+
+ // Create a server-side store.
+ NonceStore server = new NonceStore(shmem.getSystemNonceBlock(), true);
+
+ // Verify that the configured limits are as expected.
+ assertEquals(server.mMaxNonce, maxNonce);
+ assertEquals(server.mMaxByte, maxByte);
+
+ // Create mMaxNonce nonces. These all succeed.
+ for (int i = 0; i < server.mMaxNonce; i++) {
+ String name = String.format("name_%03d", i);
+ assertEquals(i, server.storeName(name));
+ }
+
+ // Verify that we cannot create a nonce over the limit.
+ try {
+ int i = server.mMaxNonce;
+ String name = String.format("name_%03d", i);
+ server.storeName(name);
+ fail("expected a RuntimeException");
+ } catch (RuntimeException e) {
+ // Okay
+ }
+
+ shmem.close();
+ }
+
// Verify that an invalid module causes an exception.
private void testInvalidModule(String module) {
try {
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index f9d449cd3b10..4ad6708cda93 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -191,7 +191,7 @@ class FontScaleConverterFactoryTest {
.fuzzFractions()
.mapNotNull{ FontScaleConverterFactory.forScale(it) }
.flatMap{ table ->
- generateSequenceOfFractions(-2000f..2000f, step = 0.1f)
+ generateSequenceOfFractions(-20f..100f, step = 0.1f)
.fuzzFractions()
.map{ Pair(table, it) }
}
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt b/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
index 6d6b56754000..286c1b94fdb8 100644
--- a/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
+++ b/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
@@ -23,6 +23,7 @@ import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
import android.hardware.display.DisplayTopology.TreeNode.POSITION_RIGHT
import android.util.SparseArray
+import android.util.SparseIntArray
import android.view.Display
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -811,6 +812,13 @@ class DisplayTopologyTest {
@Test
fun coordinates() {
+ // 1122222244
+ // 1122222244
+ // 11 44
+ // 11 44
+ // 1133333344
+ // 1133333344
+
val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* width= */ 200f,
/* height= */ 600f, /* position= */ 0, /* offset= */ 0f)
@@ -837,6 +845,243 @@ class DisplayTopologyTest {
assertThat(coords.contentEquals(expectedCoords)).isTrue()
}
+ @Test
+ fun graph() {
+ // 1122222244
+ // 1122222244
+ // 11 44
+ // 11 44
+ // 1133333344
+ // 1133333344
+ // 555
+ // 555
+ // 555
+
+ val densityPerDisplay = SparseIntArray()
+
+ val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* width= */ 200f,
+ /* height= */ 600f, /* position= */ 0, /* offset= */ 0f)
+ val density1 = 100
+ densityPerDisplay.append(1, density1)
+
+ val display2 = DisplayTopology.TreeNode(/* displayId= */ 2, /* width= */ 600f,
+ /* height= */ 200f, POSITION_RIGHT, /* offset= */ 0f)
+ display1.addChild(display2)
+ val density2 = 200
+ densityPerDisplay.append(2, density2)
+
+ val primaryDisplayId = 3
+ val display3 = DisplayTopology.TreeNode(primaryDisplayId, /* width= */ 600f,
+ /* height= */ 200f, POSITION_RIGHT, /* offset= */ 400f)
+ display1.addChild(display3)
+ val density3 = 150
+ densityPerDisplay.append(3, density3)
+
+ val display4 = DisplayTopology.TreeNode(/* displayId= */ 4, /* width= */ 200f,
+ /* height= */ 600f, POSITION_RIGHT, /* offset= */ 0f)
+ display2.addChild(display4)
+ val density4 = 300
+ densityPerDisplay.append(4, density4)
+
+ val display5 = DisplayTopology.TreeNode(/* displayId= */ 5, /* width= */ 300f,
+ /* height= */ 300f, POSITION_BOTTOM, /* offset= */ -100f)
+ display4.addChild(display5)
+ val density5 = 300
+ densityPerDisplay.append(5, density5)
+
+ topology = DisplayTopology(display1, primaryDisplayId)
+ val graph = topology.getGraph(densityPerDisplay)!!
+ val nodes = graph.displayNodes
+
+ assertThat(graph.primaryDisplayId).isEqualTo(primaryDisplayId)
+ assertThat(nodes.map {it.displayId}).containsExactly(1, 2, 3, 4, 5)
+ for (node in nodes) {
+ assertThat(node.density).isEqualTo(densityPerDisplay.get(node.displayId))
+ when (node.displayId) {
+ 1 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 2, POSITION_RIGHT,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_RIGHT,
+ /* offsetDp= */ 400f))
+ 2 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 1, POSITION_LEFT,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 4, POSITION_RIGHT,
+ /* offsetDp= */ 0f))
+ 3 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 1, POSITION_LEFT,
+ /* offsetDp= */ -400f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 4, POSITION_RIGHT,
+ /* offsetDp= */ -400f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 5, POSITION_BOTTOM,
+ /* offsetDp= */ 500f))
+ 4 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 2, POSITION_LEFT,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_LEFT,
+ /* offsetDp= */ 400f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 5, POSITION_BOTTOM,
+ /* offsetDp= */ -100f))
+ 5 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_TOP,
+ /* offsetDp= */ -500f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 4, POSITION_TOP,
+ /* offsetDp= */ 100f))
+ }
+ }
+ }
+
+ @Test
+ fun graph_corner() {
+ // 1122244
+ // 1122244
+ // 1122244
+ // 333
+ // 55
+
+ val densityPerDisplay = SparseIntArray()
+
+ val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* width= */ 200f,
+ /* height= */ 300f, /* position= */ 0, /* offset= */ 0f)
+ val density1 = 100
+ densityPerDisplay.append(1, density1)
+
+ val display2 = DisplayTopology.TreeNode(/* displayId= */ 2, /* width= */ 300f,
+ /* height= */ 300f, POSITION_RIGHT, /* offset= */ 0f)
+ display1.addChild(display2)
+ val density2 = 200
+ densityPerDisplay.append(2, density2)
+
+ val primaryDisplayId = 3
+ val display3 = DisplayTopology.TreeNode(primaryDisplayId, /* width= */ 300f,
+ /* height= */ 100f, POSITION_BOTTOM, /* offset= */ 0f)
+ display2.addChild(display3)
+ val density3 = 150
+ densityPerDisplay.append(3, density3)
+
+ val display4 = DisplayTopology.TreeNode(/* displayId= */ 4, /* width= */ 200f,
+ /* height= */ 300f, POSITION_RIGHT, /* offset= */ 0f)
+ display2.addChild(display4)
+ val density4 = 300
+ densityPerDisplay.append(4, density4)
+
+ val display5 = DisplayTopology.TreeNode(/* displayId= */ 5, /* width= */ 200f,
+ /* height= */ 100f, POSITION_BOTTOM, /* offset= */ -200f)
+ display3.addChild(display5)
+ val density5 = 300
+ densityPerDisplay.append(5, density5)
+
+ topology = DisplayTopology(display1, primaryDisplayId)
+ val graph = topology.getGraph(densityPerDisplay)!!
+ val nodes = graph.displayNodes
+
+ assertThat(graph.primaryDisplayId).isEqualTo(primaryDisplayId)
+ assertThat(nodes.map {it.displayId}).containsExactly(1, 2, 3, 4, 5)
+ for (node in nodes) {
+ assertThat(node.density).isEqualTo(densityPerDisplay.get(node.displayId))
+ when (node.displayId) {
+ 1 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 2, POSITION_RIGHT,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_RIGHT,
+ /* offsetDp= */ 300f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_BOTTOM,
+ /* offsetDp= */ 200f))
+ 2 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 1, POSITION_LEFT,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_BOTTOM,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 4, POSITION_RIGHT,
+ /* offsetDp= */ 0f))
+ 3 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 1, POSITION_LEFT,
+ /* offsetDp= */ -300f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 1, POSITION_TOP,
+ /* offsetDp= */ -200f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 2, POSITION_TOP,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 4, POSITION_RIGHT,
+ /* offsetDp= */ -300f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 4, POSITION_TOP,
+ /* offsetDp= */ 300f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 5, POSITION_LEFT,
+ /* offsetDp= */ 100f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 5, POSITION_BOTTOM,
+ /* offsetDp= */ -200f))
+ 4 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 2, POSITION_LEFT,
+ /* offsetDp= */ 0f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_LEFT,
+ /* offsetDp= */ 300f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_BOTTOM,
+ /* offsetDp= */ -300f))
+ 5 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_TOP,
+ /* offsetDp= */ 200f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_RIGHT,
+ /* offsetDp= */ -100f))
+ }
+ }
+ }
+
+ @Test
+ fun graph_smallGap() {
+ // 11122
+ // 11122
+ // 11133
+ // 11133
+
+ // There is a gap between displays 2 and 3, small enough for them to still be adjacent.
+
+ val densityPerDisplay = SparseIntArray()
+
+ val display1 = DisplayTopology.TreeNode(/* displayId= */ 1, /* width= */ 300f,
+ /* height= */ 400f, /* position= */ 0, /* offset= */ 0f)
+ val density1 = 100
+ densityPerDisplay.append(1, density1)
+
+ val display2 = DisplayTopology.TreeNode(/* displayId= */ 2, /* width= */ 200f,
+ /* height= */ 200f, POSITION_RIGHT, /* offset= */ -1f)
+ display1.addChild(display2)
+ val density2 = 200
+ densityPerDisplay.append(2, density2)
+
+ val primaryDisplayId = 3
+ val display3 = DisplayTopology.TreeNode(primaryDisplayId, /* width= */ 200f,
+ /* height= */ 200f, POSITION_RIGHT, /* offset= */ 201f)
+ display1.addChild(display3)
+ val density3 = 150
+ densityPerDisplay.append(3, density3)
+
+ topology = DisplayTopology(display1, primaryDisplayId)
+ val graph = topology.getGraph(densityPerDisplay)!!
+ val nodes = graph.displayNodes
+
+ assertThat(graph.primaryDisplayId).isEqualTo(primaryDisplayId)
+ assertThat(nodes.map {it.displayId}).containsExactly(1, 2, 3)
+ for (node in nodes) {
+ assertThat(node.density).isEqualTo(densityPerDisplay.get(node.displayId))
+ when (node.displayId) {
+ 1 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 2, POSITION_RIGHT,
+ /* offsetDp= */ -1f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_RIGHT,
+ /* offsetDp= */ 201f))
+ 2 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 1, POSITION_LEFT,
+ /* offsetDp= */ 1f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 3, POSITION_BOTTOM,
+ /* offsetDp= */ 0f))
+ 3 -> assertThat(node.adjacentDisplays.toSet()).containsExactly(
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 1, POSITION_LEFT,
+ /* offsetDp= */ -201f),
+ DisplayTopologyGraph.AdjacentDisplay(/* displayId= */ 2, POSITION_TOP,
+ /* offsetDp= */ 0f))
+ }
+ }
+ }
+
/**
* Runs the rearrange algorithm and returns the resulting tree as a list of nodes, with the
* root at index 0. The number of nodes is inferred from the number of positions passed.
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index cef6970ba25a..c40137f1bd34 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -1054,8 +1054,7 @@ public class ViewRootImplTest {
ViewRootImpl viewRootImpl = mView.getViewRootImpl();
sInstrumentation.runOnMainSync(() -> {
mView.invalidate();
- viewRootImpl.notifyInsetsAnimationRunningStateChanged(true, 0 /* animationType */,
- 0 /* insetsTypes */ /* areOtherAnimationsRunning */);
+ viewRootImpl.notifyInsetsAnimationRunningStateChanged(true);
mView.invalidate();
});
sInstrumentation.waitForIdleSync();
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index ee8d428d8370..f87b6994900f 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -224,7 +224,7 @@ public class ContentCaptureSessionTest {
}
@Override
- void internalFlush(int reason) {
+ void flush(int reason) {
throw new UnsupportedOperationException("should not have been called");
}
diff --git a/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
index a1d7f87614e4..b42bcee77c67 100644
--- a/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
@@ -263,7 +263,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -280,7 +280,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -298,7 +298,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -316,7 +316,7 @@ public class MainContentCaptureSessionTest {
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -499,57 +499,6 @@ public class MainContentCaptureSessionTest {
assertThat(session.mEventProcessQueue).hasSize(1);
}
- @Test
- public void notifyContentCaptureEvents_beforeSessionPerformStart() throws RemoteException {
- ContentCaptureOptions options =
- createOptions(
- /* enableContentCaptureReceiver= */ true,
- /* enableContentProtectionReceiver= */ true);
- MainContentCaptureSession session = createSession(options);
- session.mContentCaptureHandler = null;
- session.mDirectServiceInterface = null;
-
- notifyContentCaptureEvents(session);
- mTestableLooper.processAllMessages();
-
- assertThat(session.mEvents).isNull();
- assertThat(session.mEventProcessQueue).hasSize(7); // 5 view events + 2 view tree events
- }
-
- @Test
- public void notifyViewAppeared_beforeSessionPerformStart() throws RemoteException {
- ContentCaptureOptions options =
- createOptions(
- /* enableContentCaptureReceiver= */ true,
- /* enableContentProtectionReceiver= */ true);
- MainContentCaptureSession session = createSession(options);
- session.mContentCaptureHandler = null;
- session.mDirectServiceInterface = null;
-
- View view = prepareView(session);
- session.notifyViewAppeared(session.newViewStructure(view));
-
- assertThat(session.mEvents).isNull();
- assertThat(session.mEventProcessQueue).hasSize(1);
- }
-
- @Test
- public void flush_beforeSessionPerformStart() throws Exception {
- ContentCaptureOptions options =
- createOptions(
- /* enableContentCaptureReceiver= */ true,
- /* enableContentProtectionReceiver= */ true);
- MainContentCaptureSession session = createSession(options);
- session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
- session.mContentCaptureHandler = null;
- session.mDirectServiceInterface = null;
-
- session.internalFlush(REASON);
-
- assertThat(session.mEvents).hasSize(1);
- assertThat(session.mEventProcessQueue).isEmpty();
- }
-
/** Simulates the regular content capture events sequence. */
private void notifyContentCaptureEvents(final MainContentCaptureSession session) {
final ArrayList<Object> events = new ArrayList<>(
@@ -612,8 +561,8 @@ public class MainContentCaptureSessionTest {
sStrippedContext,
manager,
testHandler,
+ testHandler,
mMockSystemServerInterface);
- session.mContentCaptureHandler = testHandler;
session.mComponentName = COMPONENT_NAME;
return session;
}
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 2880ecf835c4..8b0d3158e9e7 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -36,6 +36,7 @@ import android.app.PendingIntent;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
@@ -934,6 +935,136 @@ public class RemoteViewsTest {
assertEquals(testText, replacedTextView.getText());
}
+ @Test
+ public void estimateMemoryUsage() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+ Bitmap b3 = Bitmap.createBitmap(800, 600, Bitmap.Config.ARGB_8888);
+ int b3Memory = b3.getAllocationByteCount();
+
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ assertEquals(0, rv.estimateMemoryUsage());
+ assertEquals(0, rv.estimateIconMemoryUsage());
+ assertEquals(0, rv.estimateTotalBitmapMemoryUsage());
+
+ rv.setBitmap(R.id.view, "", b1);
+ rv.setImageViewBitmap(R.id.view, b1); // second instance of b1 is cached
+ rv.setBitmap(R.id.view, "", b2);
+ assertEquals(b1Memory + b2Memory, rv.estimateMemoryUsage());
+ assertEquals(0, rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage());
+
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b3));
+ rv.setImageViewIcon(R.id.view, Icon.createWithBitmap(b3));
+ assertEquals(b1Memory + b2Memory, rv.estimateMemoryUsage());
+ assertEquals(b2Memory + (2 * b3Memory), rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + (2 * b2Memory) + (2 * b3Memory),
+ rv.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_landscapePortrait() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+ Bitmap b3 = Bitmap.createBitmap(800, 600, Bitmap.Config.ARGB_8888);
+ int b3Memory = b3.getAllocationByteCount();
+ Bitmap b4 = Bitmap.createBitmap(320, 240, Bitmap.Config.ARGB_8888);
+ int b4Memory = b4.getAllocationByteCount();
+
+ // Landscape and portrait using same bitmaps get counted twice.
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b1);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ RemoteViews landscapePortraitViews = new RemoteViews(rv, rv);
+ assertEquals(b1Memory, landscapePortraitViews.estimateMemoryUsage());
+ assertEquals(2 * b2Memory, landscapePortraitViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + (2 * b2Memory),
+ landscapePortraitViews.estimateTotalBitmapMemoryUsage());
+
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b3);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b4));
+ landscapePortraitViews = new RemoteViews(rv, rv2);
+ assertEquals(b1Memory + b3Memory, landscapePortraitViews.estimateMemoryUsage());
+ assertEquals(b2Memory + b4Memory, landscapePortraitViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory + b3Memory + b4Memory,
+ landscapePortraitViews.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_sizedViews() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+ Bitmap b3 = Bitmap.createBitmap(800, 600, Bitmap.Config.ARGB_8888);
+ int b3Memory = b3.getAllocationByteCount();
+ Bitmap b4 = Bitmap.createBitmap(320, 240, Bitmap.Config.ARGB_8888);
+ int b4Memory = b4.getAllocationByteCount();
+
+ // Sized views using same bitmaps do not get counted twice.
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b1);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ RemoteViews sizedViews = new RemoteViews(
+ Map.of(new SizeF(0f, 0f), rv, new SizeF(1f, 1f), rv));
+ assertEquals(b1Memory, sizedViews.estimateMemoryUsage());
+ assertEquals(2 * b2Memory, sizedViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + (2 * b2Memory), sizedViews.estimateTotalBitmapMemoryUsage());
+
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b3);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b4));
+ sizedViews = new RemoteViews(Map.of(new SizeF(0f, 0f), rv, new SizeF(1f, 1f), rv2));
+ assertEquals(b1Memory + b3Memory, sizedViews.estimateMemoryUsage());
+ assertEquals(b2Memory + b4Memory, sizedViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory + b3Memory + b4Memory,
+ sizedViews.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_nestedViews() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+
+ final RemoteViews rv1 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv1.setBitmap(R.id.view, "", b1);
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv2.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.addView(R.id.view, rv1);
+ rv.addView(R.id.view, rv2);
+ assertEquals(b1Memory, rv.estimateMemoryUsage());
+ assertEquals(b2Memory, rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_remoteCollectionItems() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+
+ final RemoteViews rv1 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv1.setBitmap(R.id.view, "", b1);
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv2.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setRemoteAdapter(R.id.view, new RemoteViews.RemoteCollectionItems.Builder().addItem(0L,
+ rv1).addItem(1L, rv2).build());
+ assertEquals(b1Memory, rv.estimateMemoryUsage());
+ assertEquals(b2Memory, rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage());
+ }
+
private static LayoutInflater.Factory2 createLayoutInflaterFactory(String viewTypeToReplace,
View replacementView) {
return new LayoutInflater.Factory2() {
diff --git a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
index ec19c0c52759..9baa31faea08 100644
--- a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
@@ -143,8 +143,8 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedRed = 0x66FF0000;
+ // Colors with 50% opacity
+ int fadedRed = 0x80FF0000;
expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 300, fadedRed, true)));
@@ -271,8 +271,8 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedBlue = 0x660000FF;
+ // Colors with 50% opacity
+ int fadedBlue = 0x800000FF;
expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 180, Color.BLUE),
new DrawableSegment(180, 300, fadedBlue, true)));
@@ -321,8 +321,8 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
+ // Colors with 50% opacity
+ int fadedGreen = 0x8000FF00;
expectedDrawableParts = new ArrayList<>(List.of(new DrawableSegment(0, 146, Color.RED),
new DrawableSegment(150, 180, Color.GREEN),
new DrawableSegment(180, 300, fadedGreen, true)));
@@ -370,8 +370,8 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
+ // Colors with 50% opacity
+ int fadedGreen = 0x8000FF00;
expectedDrawableParts = new ArrayList<>(List.of(new DrawableSegment(0, 146, Color.RED),
new DrawableSegment(150, 176, Color.GREEN),
new DrawableSegment(180, 300, fadedGreen, true)));
@@ -439,9 +439,9 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedBlue = 0x660000FF;
- int fadedYellow = 0x66FFFF00;
+ // Colors with 50% opacity
+ int fadedBlue = 0x800000FF;
+ int fadedYellow = 0x80FFFF00;
expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 34.219177F, Color.BLUE),
new DrawablePoint(38.219177F, 50.219177F, Color.RED),
@@ -517,9 +517,9 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
- int fadedYellow = 0x66FFFF00;
+ // Colors with 50% opacity
+ int fadedGreen = 0x8000FF00;
+ int fadedYellow = 0x80FFFF00;
expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 34.095238F, Color.RED),
new DrawablePoint(38.095238F, 50.095238F, Color.RED),
@@ -594,9 +594,9 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
- int fadedYellow = 0x66FFFF00;
+ // Colors with 50% opacity
+ int fadedGreen = 0x8000FF00;
+ int fadedYellow = 0x80FFFF00;
expectedDrawableParts = new ArrayList<>(
List.of(new DrawablePoint(0, 12, Color.RED),
new DrawableSegment(16, 65, Color.RED),
@@ -675,9 +675,9 @@ public class NotificationProgressBarTest {
parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
- int fadedYellow = 0x66FFFF00;
+ // Colors with 50% opacity
+ int fadedGreen = 0x8000FF00;
+ int fadedYellow = 0x80FFFF00;
expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 16, Color.RED),
new DrawablePoint(20, 32, Color.RED),
@@ -1039,9 +1039,9 @@ public class NotificationProgressBarTest {
isStyledByProgress
);
- // Colors with 40% opacity
- int fadedBlue = 0x660000FF;
- int fadedYellow = 0x66FFFF00;
+ // Colors with 50% opacity
+ int fadedBlue = 0x800000FF;
+ int fadedYellow = 0x80FFFF00;
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 34.219177F, Color.BLUE),
new DrawablePoint(38.219177F, 50.219177F, Color.RED),
@@ -1089,8 +1089,8 @@ public class NotificationProgressBarTest {
isStyledByProgress
);
- // Colors with 40% opacity
- int fadedBlue = 0x660000FF;
+ // Colors with 50%f opacity
+ int fadedBlue = 0x800000FF;
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 60.000004F, Color.BLUE),
new DrawableSegment(60.000004F, 100, fadedBlue, true)));
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 065644627393..13d0169c47c5 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -177,10 +177,3 @@ flag {
description: "Factor task-view state tracking out of taskviewtransitions"
bug: "384976265"
}
-
-flag {
- name: "enable_non_default_display_split"
- namespace: "multitasking"
- description: "Enables split screen on non default displays"
- bug: "384999213"
-}
diff --git a/libs/WindowManager/Shell/res/layout/desktop_windowing_education_left_arrow_tooltip.xml b/libs/WindowManager/Shell/res/layout/desktop_windowing_education_horizontal_arrow_tooltip.xml
index fd75827cff75..d159a274e150 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_windowing_education_left_arrow_tooltip.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_windowing_education_horizontal_arrow_tooltip.xml
@@ -18,7 +18,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="1dp"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:gravity="start">
<!-- ImageView for the arrow icon, positioned horizontally at the start of the tooltip
container. -->
diff --git a/libs/WindowManager/Shell/res/values/ids.xml b/libs/WindowManager/Shell/res/values/ids.xml
index debcba071d9c..122cde04f8e4 100644
--- a/libs/WindowManager/Shell/res/values/ids.xml
+++ b/libs/WindowManager/Shell/res/values/ids.xml
@@ -46,4 +46,9 @@
<item type="id" name="action_move_bubble_bar_right"/>
<item type="id" name="dismiss_view"/>
+
+ <!-- Accessibility actions for desktop windowing. -->
+ <item type="id" name="action_snap_left"/>
+ <item type="id" name="action_snap_right"/>
+ <item type="id" name="action_maximize_restore"/>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 468c345259d0..c29b927f61c2 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -333,6 +333,28 @@
<!-- Accessibility text for the Maximize Menu's snap right button [CHAR LIMIT=NONE] -->
<string name="desktop_mode_maximize_menu_snap_right_button_text">Snap right</string>
+ <!-- Accessibility text for the Maximize Menu's snap left button [CHAR LIMIT=NONE] -->
+ <string name="desktop_mode_a11y_action_snap_left">Resize app window left</string>
+ <!-- Accessibility text for the Maximize Menu's snap right button [CHAR LIMIT=NONE] -->
+ <string name="desktop_mode_a11y_action_snap_right">Resize app window right</string>
+ <!-- Accessibility text for the Maximize Menu's snap maximize/restore [CHAR LIMIT=NONE] -->
+ <string name="desktop_mode_a11y_action_maximize_restore">Maximize or restore window size</string>
+
+ <!-- Accessibility action replacement for caption handle menu split screen button [CHAR LIMIT=NONE] -->
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text">Enter split screen mode</string>
+ <!-- Accessibility action replacement for caption handle menu enter desktop mode button [CHAR LIMIT=NONE] -->
+ <string name="app_handle_menu_talkback_desktop_mode_button_text">Enter desktop windowing mode</string>
+ <!-- Accessibility action replacement for maximize menu enter snap left button [CHAR LIMIT=NONE] -->
+ <string name="maximize_menu_talkback_action_snap_left_text">Resize window to left</string>
+ <!-- Accessibility action replacement for maximize menu enter snap right button [CHAR LIMIT=NONE] -->
+ <string name="maximize_menu_talkback_action_snap_right_text">Resize window to right</string>
+ <!-- Accessibility action replacement for maximize menu enter maximize/restore button [CHAR LIMIT=NONE] -->
+ <string name="maximize_menu_talkback_action_maximize_restore_text">Maximize or restore window size</string>
+ <!-- Accessibility action replacement for app header maximize/restore button [CHAR LIMIT=NONE] -->
+ <string name="maximize_button_talkback_action_maximize_restore_text">Maximize or restore window size</string>
+ <!-- Accessibility action replacement for app header minimize button [CHAR LIMIT=NONE] -->
+ <string name="minimize_button_talkback_action_maximize_restore_text">Minimize app window</string>
+
<!-- Accessibility text for open by default settings button [CHAR LIMIT=NONE] -->
<string name="open_by_default_settings_text">Open by default settings</string>
<!-- Subheader for open by default menu string. -->
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/PhysicsAnimator.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/PhysicsAnimator.kt
index 9d3b56d22a2f..812b3585840a 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/PhysicsAnimator.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/PhysicsAnimator.kt
@@ -985,6 +985,11 @@ class PhysicsAnimator<T> private constructor (target: T) {
return animators[target] as PhysicsAnimator<T>
}
+ @JvmStatic
+ @Suppress("UNCHECKED_CAST")
+ fun <T: Any> getInstanceIfExists(target: T): PhysicsAnimator<T>? =
+ animators[target] as PhysicsAnimator<T>?
+
/**
* Set whether all physics animators should log a lot of information about animations.
* Useful for debugging!
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/WindowAnimator.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/WindowAnimator.kt
index 91d66eaeb088..d1c34a4ac1cf 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/WindowAnimator.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/WindowAnimator.kt
@@ -22,6 +22,7 @@ import android.graphics.PointF
import android.graphics.Rect
import android.util.DisplayMetrics
import android.util.TypedValue
+import android.view.Choreographer
import android.view.SurfaceControl
import android.view.animation.Interpolator
import android.window.TransitionInfo
@@ -82,6 +83,7 @@ object WindowAnimator {
transaction
.setPosition(leash, animPos.x, animPos.y)
.setScale(leash, animScale, animScale)
+ .setFrameTimeline(Choreographer.getInstance().vsyncId)
.apply()
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index a65e69eee5fe..c40a276cb7bd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -56,6 +56,7 @@ import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
+import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.shared.bubbles.BubbleInfo;
import com.android.wm.shell.shared.bubbles.ParcelableFlyoutMessage;
import com.android.wm.shell.taskview.TaskView;
@@ -1093,7 +1094,7 @@ public class Bubble implements BubbleViewProvider {
* intent for an app. In this case we don't show a badge on the icon.
*/
public boolean isAppLaunchIntent() {
- if (Flags.enableBubbleAnything() && mAppIntent != null) {
+ if (BubbleAnythingFlagHelper.enableCreateAnyBubble() && mAppIntent != null) {
return mAppIntent.hasCategory("android.intent.category.LAUNCHER");
}
return false;
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 5f2b95f7b137..e3f8e0c321a4 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
@@ -640,6 +640,14 @@ public class BubbleController implements ConfigurationChangeListener,
mOnImeHidden = onImeHidden;
mBubblePositioner.setImeVisible(false /* visible */, 0 /* height */);
int displayId = mWindowManager.getDefaultDisplay().getDisplayId();
+ // if the device is locked we can't use the status bar service to hide the IME because
+ // the IME state is frozen and it will lead to internal IME state going out of sync. This
+ // will make the IME visible when the device is unlocked. Instead we use
+ // DisplayImeController directly to make sure the state is correct when the device unlocks.
+ if (isDeviceLocked()) {
+ mDisplayImeController.hideImeForBubblesWhenLocked(displayId);
+ return;
+ }
try {
mBarService.hideCurrentInputMethodForBubbles(displayId);
} catch (RemoteException e) {
@@ -679,8 +687,20 @@ public class BubbleController implements ConfigurationChangeListener,
? mNotifEntryToExpandOnShadeUnlock.getKey() : "null"));
mIsStatusBarShade = isShade;
if (!mIsStatusBarShade && didChange) {
- // Only collapse stack on change
- collapseStack();
+ if (mBubbleData.isExpanded()) {
+ // If the IME is visible, hide it first and then collapse.
+ if (mBubblePositioner.isImeVisible()) {
+ hideCurrentInputMethod(this::collapseStack);
+ } else {
+ collapseStack();
+ }
+ } else if (mOnImeHidden != null) {
+ // a request to collapse started before we're notified that the device is locking.
+ // we're currently waiting for the IME to collapse, before mOnImeHidden can be
+ // executed, which may not happen since the screen may already be off. hide the IME
+ // immediately now that we're locked and pass the same runnable so it can complete.
+ hideCurrentInputMethod(mOnImeHidden);
+ }
}
if (mNotifEntryToExpandOnShadeUnlock != null) {
@@ -1433,7 +1453,7 @@ public class BubbleController implements ConfigurationChangeListener,
* @param info the shortcut info for the bubble.
*/
public void expandStackAndSelectBubble(ShortcutInfo info) {
- if (!Flags.enableBubbleAnything()) return;
+ if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
Bubble b = mBubbleData.getOrCreateBubble(info); // Removes from overflow
ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - shortcut=%s", info);
if (b.isInflated()) {
@@ -1450,7 +1470,7 @@ public class BubbleController implements ConfigurationChangeListener,
* @param intent the intent for the bubble.
*/
public void expandStackAndSelectBubble(Intent intent, UserHandle user) {
- if (!Flags.enableBubbleAnything()) return;
+ if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
Bubble b = mBubbleData.getOrCreateBubble(intent, user); // Removes from overflow
ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", intent);
if (b.isInflated()) {
@@ -2483,6 +2503,10 @@ public class BubbleController implements ConfigurationChangeListener,
mBubbleData.setSelectedBubbleAndExpandStack(bubbleToSelect);
}
+ private boolean isDeviceLocked() {
+ return !mIsStatusBarShade;
+ }
+
/**
* Description of current bubble state.
*/
@@ -2516,7 +2540,7 @@ public class BubbleController implements ConfigurationChangeListener,
* @param entry the entry to bubble.
*/
static boolean canLaunchInTaskView(Context context, BubbleEntry entry) {
- if (Flags.enableBubbleAnything()) return true;
+ if (BubbleAnythingFlagHelper.enableCreateAnyBubble()) return true;
PendingIntent intent = entry.getBubbleMetadata() != null
? entry.getBubbleMetadata().getIntent()
: null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 13f8e9ef9dd3..97b03a9f58e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -71,6 +71,7 @@ import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.common.AlphaOptimizedButton;
import com.android.wm.shell.shared.TriangleShape;
+import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.taskview.TaskView;
import java.io.PrintWriter;
@@ -226,7 +227,8 @@ public class BubbleExpandedView extends LinearLayout {
MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS);
final boolean isShortcutBubble = (mBubble.hasMetadataShortcutId()
- || (mBubble.getShortcutInfo() != null && Flags.enableBubbleAnything()));
+ || (mBubble.getShortcutInfo() != null
+ && BubbleAnythingFlagHelper.enableCreateAnyBubble()));
if (mBubble.isAppBubble()) {
Context context =
@@ -687,11 +689,6 @@ public class BubbleExpandedView extends LinearLayout {
}
}
- /** Sets the alpha for the pointer. */
- public void setPointerAlpha(float alpha) {
- mPointerView.setAlpha(alpha);
- }
-
/**
* Get alpha from underlying {@code TaskView} if this view is for a bubble.
* Or get alpha for the overflow view if this view is for overflow.
@@ -794,24 +791,6 @@ public class BubbleExpandedView extends LinearLayout {
onContainerClipUpdate();
}
- /**
- * Sets the clipping for the view.
- */
- public void setTaskViewClip(Rect rect) {
- mLeftClip = rect.left;
- mTopClip = rect.top;
- mRightClip = rect.right;
- mBottomClip = rect.bottom;
- onContainerClipUpdate();
- }
-
- /**
- * Returns a rect representing the clipping for the view.
- */
- public Rect getTaskViewClip() {
- return new Rect(mLeftClip, mTopClip, mRightClip, mBottom);
- }
-
private void onContainerClipUpdate() {
if (mTopClip == 0 && mBottomClip == 0 && mRightClip == 0 && mLeftClip == 0) {
if (mIsClipping) {
@@ -1122,13 +1101,6 @@ public class BubbleExpandedView extends LinearLayout {
}
/**
- * Return width of the current pointer
- */
- public int getPointerWidth() {
- return mPointerWidth;
- }
-
- /**
* Position of the manage button displayed in the expanded view. Used for placing user
* education about the manage button.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
index 62995319db80..086c91985ae3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
@@ -137,14 +137,15 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl
// Update bitmap
val fg = InsetDrawable(overflowBtn?.iconDrawable, overflowIconInset)
val drawable = AdaptiveIconDrawable(ColorDrawable(colorAccent), fg)
- bitmap = iconFactory.createBadgedIconBitmap(drawable).icon
+ val bubbleBitmapScale = FloatArray(1)
+ bitmap = iconFactory.getBubbleBitmap(drawable, bubbleBitmapScale)
// Update dot path
dotPath =
PathParser.createPathFromPathData(
res.getString(com.android.internal.R.string.config_icon_mask)
)
- val scale = iconFactory.normalizer.getScale(iconView!!.iconDrawable)
+ val scale = bubbleBitmapScale[0]
val radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f
val matrix = Matrix()
matrix.setScale(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
index ae84f449c0e4..a6b858500dcb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
@@ -36,7 +36,7 @@ import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.android.internal.protolog.ProtoLog;
-import com.android.wm.shell.Flags;
+import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.taskview.TaskView;
/**
@@ -108,7 +108,8 @@ public class BubbleTaskViewHelper {
options.setPendingIntentBackgroundActivityStartMode(
MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS);
final boolean isShortcutBubble = (mBubble.hasMetadataShortcutId()
- || (mBubble.getShortcutInfo() != null && Flags.enableBubbleAnything()));
+ || (mBubble.getShortcutInfo() != null
+ && BubbleAnythingFlagHelper.enableCreateAnyBubble()));
if (mBubble.getPreparingTransition() != null) {
mBubble.getPreparingTransition().surfaceCreated();
} else if (mBubble.isAppBubble()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 94e629a6887f..8377a35a9e7d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -224,6 +224,12 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
}
+ /** Hides the IME for Bubbles when the device is locked. */
+ public void hideImeForBubblesWhenLocked(int displayId) {
+ PerDisplay pd = mImePerDisplay.get(displayId);
+ pd.setImeInputTargetRequestedVisibility(false, pd.getImeSourceControl().getImeStatsToken());
+ }
+
/** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */
public class PerDisplay implements DisplayInsetsController.OnInsetsChangedListener {
final int mDisplayId;
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 cd5c135691d7..bd89f5cf45f6 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
@@ -394,11 +394,19 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
* Returns the divider position as a fraction from 0 to 1.
*/
public float getDividerPositionAsFraction() {
- return Math.min(1f, Math.max(0f, mIsLeftRightSplit
- ? (float) ((getTopLeftBounds().right + getBottomRightBounds().left) / 2f)
- / getBottomRightBounds().right
- : (float) ((getTopLeftBounds().bottom + getBottomRightBounds().top) / 2f)
- / getBottomRightBounds().bottom));
+ if (Flags.enableFlexibleTwoAppSplit()) {
+ return Math.min(1f, Math.max(0f, mIsLeftRightSplit
+ ? (getTopLeftBounds().right + getBottomRightBounds().left) / 2f
+ / getDisplayWidth()
+ : (getTopLeftBounds().bottom + getBottomRightBounds().top) / 2f
+ / getDisplayHeight()));
+ } else {
+ return Math.min(1f, Math.max(0f, mIsLeftRightSplit
+ ? (float) ((getTopLeftBounds().right + getBottomRightBounds().left) / 2f)
+ / getBottomRightBounds().right
+ : (float) ((getTopLeftBounds().bottom + getBottomRightBounds().top) / 2f)
+ / getBottomRightBounds().bottom));
+ }
}
private void updateInvisibleRect() {
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 1323fe0fa9ca..201870fe0181 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
@@ -37,9 +37,9 @@ import android.view.Display;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.accessibility.AccessibilityManager;
+import android.window.DesktopModeFlags;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayController.OnDisplaysChangedListener;
@@ -71,7 +71,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
-import java.util.function.IntPredicate;
import java.util.function.Predicate;
/**
@@ -874,6 +873,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
}
boolean isDesktopModeShowing = mDesktopUserRepositories.get().getCurrent()
.getVisibleTaskCount(taskInfo.displayId) > 0;
- return Flags.skipCompatUiEducationInDesktopMode() && isDesktopModeShowing;
+ return DesktopModeFlags.ENABLE_DESKTOP_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE_BUGFIX
+ .isTrue() && isDesktopModeShowing;
}
}
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 e0a829df79ad..43f1a1037cab 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
@@ -31,6 +31,7 @@ import android.os.SystemProperties;
import android.provider.Settings;
import android.view.IWindowManager;
import android.view.accessibility.AccessibilityManager;
+import android.window.DesktopModeFlags;
import android.window.SystemPerformanceHinter;
import com.android.internal.logging.UiEventLogger;
@@ -315,7 +316,7 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static CompatUIStatusManager provideCompatUIStatusManager(@NonNull Context context) {
- if (Flags.enableCompatUiVisibilityStatus()) {
+ if (DesktopModeFlags.ENABLE_DESKTOP_COMPAT_UI_VISIBILITY_STATUS.isTrue()) {
return new CompatUIStatusManager(
newState -> Settings.Secure.putInt(context.getContentResolver(),
COMPAT_UI_EDUCATION_SHOWING, newState),
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 4bbe22a59315..c81838f56a74 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
@@ -16,7 +16,7 @@
package com.android.wm.shell.dagger;
-import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS;
+import static android.window.DesktopModeFlags.ENABLE_DESKTOP_SYSTEM_DIALOGS_TRANSITIONS;
import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX;
import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY;
import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT;
@@ -911,9 +911,7 @@ public abstract class WMShellModule {
Transitions transitions,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
InteractionJankMonitor interactionJankMonitor) {
- return (Flags.enableDesktopWindowingTransitions()
- || ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS.isTrue()
- || ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX.isTrue())
+ return ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX.isTrue()
? new SpringDragToDesktopTransitionHandler(
context, transitions, rootTaskDisplayAreaOrganizer, interactionJankMonitor)
: new DefaultDragToDesktopTransitionHandler(
@@ -1023,7 +1021,7 @@ public abstract class WMShellModule {
DesktopModeCompatPolicy desktopModeCompatPolicy) {
if (!DesktopModeStatus.canEnterDesktopMode(context)
|| !ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue()
- || !Flags.enableDesktopSystemDialogsTransitions()) {
+ || !ENABLE_DESKTOP_SYSTEM_DIALOGS_TRANSITIONS.isTrue()) {
return Optional.empty();
}
return Optional.of(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
index 996d71c043c2..9666ca95bcc6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
@@ -31,7 +31,6 @@ import android.window.TransitionInfo.Change
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import androidx.annotation.VisibleForTesting
-import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.protolog.ProtoLog
import com.android.window.flags.Flags
@@ -83,10 +82,7 @@ class DesktopMixedTransitionHandler(
/** Starts close transition and handles or delegates desktop task close animation. */
override fun startRemoveTransition(wct: WindowContainerTransaction?): IBinder {
- if (
- !DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue &&
- !DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX.isTrue
- ) {
+ if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX.isTrue) {
return freeformTaskTransitionHandler.startRemoveTransition(wct)
}
requireNotNull(wct)
@@ -110,7 +106,6 @@ class DesktopMixedTransitionHandler(
): IBinder {
if (
!Flags.enableFullyImmersiveInDesktop() &&
- !DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue &&
!DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue
) {
return transitions.startTransition(transitionType, wct, /* handler= */ null)
@@ -208,7 +203,6 @@ class DesktopMixedTransitionHandler(
return dispatchCloseLastDesktopTaskAnimation(
transition,
info,
- closeChange,
startTransaction,
finishTransaction,
finishCallback,
@@ -259,10 +253,7 @@ class DesktopMixedTransitionHandler(
minimizeChange?.taskInfo?.taskId,
immersiveExitChange?.taskInfo?.taskId,
)
- if (
- DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue ||
- DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue
- ) {
+ if (DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue) {
// Only apply minimize change reparenting here if we implement the new app launch
// transitions, otherwise this reparenting is handled in the default handler.
minimizeChange?.let {
@@ -352,18 +343,10 @@ class DesktopMixedTransitionHandler(
private fun dispatchCloseLastDesktopTaskAnimation(
transition: IBinder,
info: TransitionInfo,
- change: TransitionInfo.Change,
startTransaction: SurfaceControl.Transaction,
finishTransaction: SurfaceControl.Transaction,
finishCallback: TransitionFinishCallback,
): Boolean {
- // Starting the jank trace if closing the last window in desktop mode.
- interactionJankMonitor.begin(
- change.leash,
- context,
- handler,
- CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE,
- )
// Dispatch the last desktop task closing animation.
return dispatchToLeftoverHandler(
transition = transition,
@@ -371,10 +354,6 @@ class DesktopMixedTransitionHandler(
startTransaction = startTransaction,
finishTransaction = finishTransaction,
finishCallback = finishCallback,
- doOnFinishCallback = {
- // Finish the jank trace when closing the last window in desktop mode.
- interactionJankMonitor.end(CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE)
- },
)
}
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 ca71cf303a1c..b09d324833e8 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
@@ -56,6 +56,7 @@ import android.view.WindowManager.TRANSIT_TO_FRONT
import android.widget.Toast
import android.window.DesktopModeFlags
import android.window.DesktopModeFlags.DISABLE_NON_RESIZABLE_APP_SNAP_RESIZE
+import android.window.DesktopModeFlags.ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER
import android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY
import android.window.DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS
import android.window.RemoteTransition
@@ -774,6 +775,12 @@ class DesktopTasksController(
val wct = WindowContainerTransaction()
addMoveToFullscreenChanges(wct, task)
+ // We are moving a freeform task to fullscreen, put the home task under the fullscreen task.
+ if (!forceEnterDesktop(task.displayId)) {
+ moveHomeTask(wct, toTop = true, task.displayId)
+ wct.reorder(task.token, /* onTop= */ true)
+ }
+
exitDesktopTaskTransitionHandler.startTransition(
transitionSource,
wct,
@@ -1515,7 +1522,7 @@ class DesktopTasksController(
private fun addWallpaperActivity(displayId: Int, wct: WindowContainerTransaction) {
logV("addWallpaperActivity")
- if (Flags.enableDesktopWallpaperActivityForSystemUser()) {
+ if (ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER.isTrue()) {
val intent = Intent(context, DesktopWallpaperActivity::class.java)
if (
desktopWallpaperActivityTokenProvider.getToken(displayId) == null &&
@@ -1578,7 +1585,7 @@ class DesktopTasksController(
private fun removeWallpaperActivity(wct: WindowContainerTransaction, displayId: Int) {
desktopWallpaperActivityTokenProvider.getToken(displayId)?.let { token ->
logV("removeWallpaperActivity")
- if (Flags.enableDesktopWallpaperActivityForSystemUser()) {
+ if (ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER.isTrue()) {
wct.reorder(token, /* onTop= */ false)
} else {
wct.removeTask(token)
@@ -2345,10 +2352,7 @@ class DesktopTasksController(
launchTaskId: Int,
minimizeTaskId: Int?,
) {
- if (
- !DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue &&
- !DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue
- ) {
+ if (!DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue) {
return
}
// TODO b/359523924: pass immersive task here?
@@ -2505,7 +2509,6 @@ class DesktopTasksController(
*
* @param taskInfo the task being dragged.
* @param taskSurface the leash of the task being dragged.
- * @param position position of surface when drag ends.
* @param inputCoordinate the coordinates of the motion event
* @param currentDragBounds the current bounds of where the visible task is (might be actual
* task bounds or just task leash)
@@ -2515,7 +2518,6 @@ class DesktopTasksController(
fun onDragPositioningEnd(
taskInfo: RunningTaskInfo,
taskSurface: SurfaceControl,
- position: Point,
inputCoordinate: PointF,
currentDragBounds: Rect,
validDragArea: Rect,
@@ -2543,7 +2545,7 @@ class DesktopTasksController(
)
moveToFullscreenWithAnimation(
taskInfo,
- position,
+ Point(currentDragBounds.left, currentDragBounds.top),
DesktopModeTransitionSource.TASK_DRAG,
)
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
index 14c8429766cc..b3648699ed0b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -27,6 +27,7 @@ import android.view.WindowManager.TRANSIT_PIP
import android.view.WindowManager.TRANSIT_TO_BACK
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.DesktopModeFlags
+import android.window.DesktopModeFlags.ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER
import android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY
import android.window.TransitionInfo
import android.window.WindowContainerTransaction
@@ -275,7 +276,7 @@ class DesktopTasksTransitionObserver(
desktopWallpaperActivityTokenProvider
.getToken(lastSeenTransitionToCloseWallpaper.displayId)
?.let { wallpaperActivityToken ->
- if (Flags.enableDesktopWallpaperActivityForSystemUser()) {
+ if (ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER.isTrue()) {
transitions.startTransition(
TRANSIT_TO_BACK,
WindowContainerTransaction()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
index 13576aa42737..a5ba6612bb1a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
@@ -21,9 +21,9 @@ import android.content.Context
import android.content.pm.UserInfo
import android.os.UserManager
import android.util.SparseArray
+import android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_HSUM
import androidx.core.util.forEach
import com.android.internal.protolog.ProtoLog
-import com.android.window.flags.Flags
import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository
import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
@@ -68,7 +68,7 @@ class DesktopUserRepositories(
if (DesktopModeStatus.canEnterDesktopMode(context)) {
shellInit.addInitCallback(::onInit, this)
}
- if (Flags.enableDesktopWindowingHsum()) {
+ if (ENABLE_DESKTOP_WINDOWING_HSUM.isTrue()) {
userIdToProfileIdsMap[userId] = userManager.getProfiles(userId).map { it.id }
}
}
@@ -80,7 +80,7 @@ class DesktopUserRepositories(
/** Returns [DesktopRepository] for the parent user id. */
fun getProfile(profileId: Int): DesktopRepository {
- if (Flags.enableDesktopWindowingHsum()) {
+ if (ENABLE_DESKTOP_WINDOWING_HSUM.isTrue()) {
for ((uid, profileIds) in userIdToProfileIdsMap) {
if (profileId in profileIds) {
return desktopRepoByUserId.getOrCreate(uid)
@@ -101,14 +101,14 @@ class DesktopUserRepositories(
override fun onUserChanged(newUserId: Int, userContext: Context) {
logD("onUserChanged previousUserId=%d, newUserId=%d", userId, newUserId)
userId = newUserId
- if (Flags.enableDesktopWindowingHsum()) {
+ if (ENABLE_DESKTOP_WINDOWING_HSUM.isTrue()) {
sanitizeUsers()
}
}
override fun onUserProfilesChanged(profiles: MutableList<UserInfo>) {
logD("onUserProfilesChanged profiles=%s", profiles.toString())
- if (Flags.enableDesktopWindowingHsum()) {
+ if (ENABLE_DESKTOP_WINDOWING_HSUM.isTrue()) {
// TODO(b/366397912): Remove all persisted profile data when the profile changes.
userIdToProfileIdsMap[userId] = profiles.map { it.id }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java
index b902bb4394b5..f7f87ed63003 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java
@@ -32,6 +32,7 @@ import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.util.DisplayMetrics;
+import android.view.Choreographer;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManager.TransitionType;
@@ -184,6 +185,7 @@ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionH
t.setPosition(sc, mPosition.x * (1 - fraction), mPosition.y * (1 - fraction))
.setScale(sc, currentScaleX, currentScaleY)
.show(sc)
+ .setFrameTimeline(Choreographer.getInstance().getVsyncId())
.apply();
});
animator.addListener(new AnimatorListenerAdapter() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
index b614b3f4d025..5d8355625b94 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
@@ -22,6 +22,7 @@ import android.content.Context
import android.content.res.Resources
import android.graphics.Point
import android.os.SystemProperties
+import android.view.View.LAYOUT_DIRECTION_RTL
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.desktopmode.CaptionState
@@ -36,6 +37,7 @@ import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationToolt
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipEducationViewConfig
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainCoroutineDispatcher
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.filter
@@ -88,6 +90,8 @@ class AppHandleEducationController(
showEducation(captionState)
appHandleEducationDatastoreRepository
.updateAppHandleHintViewedTimestampMillis(true)
+ delay(TOOLTIP_VISIBLE_DURATION_MILLIS)
+ windowingEducationViewController.hideEducationTooltip()
}
}
@@ -109,6 +113,8 @@ class AppHandleEducationController(
showWindowingImageButtonTooltip(captionState as CaptionState.AppHandle)
appHandleEducationDatastoreRepository
.updateEnterDesktopModeHintViewedTimestampMillis(true)
+ delay(TOOLTIP_VISIBLE_DURATION_MILLIS)
+ windowingEducationViewController.hideEducationTooltip()
}
}
@@ -130,8 +136,31 @@ class AppHandleEducationController(
showExitWindowingTooltip(captionState as CaptionState.AppHeader)
appHandleEducationDatastoreRepository
.updateExitDesktopModeHintViewedTimestampMillis(true)
+ delay(TOOLTIP_VISIBLE_DURATION_MILLIS)
+ windowingEducationViewController.hideEducationTooltip()
}
}
+
+ // Listens to a [NoCaption] state change to dismiss any tooltip if the app handle or app
+ // header is gone or de-focused (e.g. when a user swipes up to home, overview, or enters
+ // split screen)
+ applicationCoroutineScope.launch {
+ if (
+ isAppHandleHintViewed() &&
+ isEnterDesktopModeHintViewed() &&
+ isExitDesktopModeHintViewed()
+ )
+ return@launch
+ windowDecorCaptionHandleRepository.captionStateFlow
+ .filter { captionState ->
+ captionState is CaptionState.NoCaption &&
+ !isAppHandleHintViewed() &&
+ !isEnterDesktopModeHintViewed() &&
+ !isExitDesktopModeHintViewed()
+ }
+ .flowOn(backgroundDispatcher)
+ .collectLatest { windowingEducationViewController.hideEducationTooltip() }
+ }
}
}
@@ -144,8 +173,6 @@ class AppHandleEducationController(
val appHandleBounds = (captionState as CaptionState.AppHandle).globalAppHandleBounds
val tooltipGlobalCoordinates =
Point(appHandleBounds.left + appHandleBounds.width() / 2, appHandleBounds.bottom)
- // TODO: b/370546801 - Differentiate between user dismissing the tooltip vs following the
- // cue.
// Populate information important to inflate app handle education tooltip.
val appHandleTooltipConfig =
TooltipEducationViewConfig(
@@ -187,9 +214,14 @@ class AppHandleEducationController(
getSize(R.dimen.desktop_mode_handle_menu_pill_spacing_margin)
val appHandleBounds = captionState.globalAppHandleBounds
+ val appHandleCenterX = appHandleBounds.left + appHandleBounds.width() / 2
val tooltipGlobalCoordinates =
Point(
- appHandleBounds.left + appHandleBounds.width() / 2 + appHandleMenuWidth / 2,
+ if (isRtl()) {
+ appHandleCenterX - appHandleMenuWidth / 2
+ } else {
+ appHandleCenterX + appHandleMenuWidth / 2
+ },
appHandleBounds.top +
appHandleMenuMargins +
appInfoPillHeight +
@@ -199,7 +231,7 @@ class AppHandleEducationController(
// tooltip.
val windowingImageButtonTooltipConfig =
TooltipEducationViewConfig(
- tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip,
+ tooltipViewLayout = R.layout.desktop_windowing_education_horizontal_arrow_tooltip,
tooltipColorScheme =
TooltipColorScheme(
tertiaryFixedColor,
@@ -210,7 +242,7 @@ class AppHandleEducationController(
tooltipText =
getString(R.string.windowing_desktop_mode_image_button_education_tooltip),
arrowDirection =
- DesktopWindowingEducationTooltipController.TooltipArrowDirection.LEFT,
+ DesktopWindowingEducationTooltipController.TooltipArrowDirection.HORIZONTAL,
onEducationClickAction = {
toDesktopModeCallback(
captionState.runningTaskInfo.taskId,
@@ -233,13 +265,17 @@ class AppHandleEducationController(
val globalAppChipBounds = captionState.globalAppChipBounds
val tooltipGlobalCoordinates =
Point(
- globalAppChipBounds.right,
+ if (isRtl()) {
+ globalAppChipBounds.left
+ } else {
+ globalAppChipBounds.right
+ },
globalAppChipBounds.top + globalAppChipBounds.height() / 2,
)
// Populate information important to inflate exit desktop mode education tooltip.
val exitWindowingTooltipConfig =
TooltipEducationViewConfig(
- tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip,
+ tooltipViewLayout = R.layout.desktop_windowing_education_horizontal_arrow_tooltip,
tooltipColorScheme =
TooltipColorScheme(
tertiaryFixedColor,
@@ -249,7 +285,7 @@ class AppHandleEducationController(
tooltipViewGlobalCoordinates = tooltipGlobalCoordinates,
tooltipText = getString(R.string.windowing_desktop_mode_exit_education_tooltip),
arrowDirection =
- DesktopWindowingEducationTooltipController.TooltipArrowDirection.LEFT,
+ DesktopWindowingEducationTooltipController.TooltipArrowDirection.HORIZONTAL,
onDismissAction = {
// TODO: b/341320146 - Log previous tooltip was dismissed
},
@@ -299,6 +335,8 @@ class AppHandleEducationController(
private fun getString(@StringRes resId: Int): String = context.resources.getString(resId)
+ private fun isRtl() = context.resources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
+
companion object {
const val TAG = "AppHandleEducationController"
val APP_HANDLE_EDUCATION_DELAY_MILLIS: Long
@@ -311,6 +349,9 @@ class AppHandleEducationController(
400L,
)
+ val TOOLTIP_VISIBLE_DURATION_MILLIS: Long
+ get() = SystemProperties.getLong("persist.windowing_tooltip_visible_duration", 12000L)
+
val FORCE_SHOW_DESKTOP_MODE_EDUCATION: Boolean
get() =
SystemProperties.getBoolean(
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 20b8c5ec45ce..d5cb2e5c88d3 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
@@ -24,7 +24,6 @@ import static android.view.Surface.ROTATION_90;
import static com.android.wm.shell.pip.PipTransitionController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipTransitionController.ANIM_TYPE_BOUNDS;
-import android.animation.AnimationHandler;
import android.animation.Animator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
@@ -42,7 +41,6 @@ import android.view.SurfaceControl;
import android.window.TaskSnapshot;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.protolog.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.common.pip.PipUtils;
@@ -110,13 +108,6 @@ public class PipAnimationController {
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
- private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
- ThreadLocal.withInitial(() -> {
- AnimationHandler handler = new AnimationHandler();
- handler.setProvider(new SfVsyncFrameCallbackProvider());
- return handler;
- });
-
private PipTransitionAnimator mCurrentAnimator;
@PipTransitionController.AnimationType
private int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
@@ -210,7 +201,6 @@ public class PipAnimationController {
animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
animator.setFloatValues(FRACTION_START, FRACTION_END);
- animator.setAnimationHandler(mSfAnimationHandlerThreadLocal.get());
return animator;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
index 2f9371536a16..d735375b0fc9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
@@ -133,7 +133,9 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener,
taskInfo.topActivity, mPipTransitionState, mPictureInPictureParams, params);
setPictureInPictureParams(params);
float newAspectRatio = mPictureInPictureParams.getAspectRatioFloat();
- if (PipUtils.aspectRatioChanged(newAspectRatio, mPipBoundsState.getAspectRatio())) {
+ if (params.hasSetAspectRatio()
+ && mPipBoundsAlgorithm.isValidPictureInPictureAspectRatio(newAspectRatio)
+ && PipUtils.aspectRatioChanged(newAspectRatio, mPipBoundsState.getAspectRatio())) {
mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> {
onAspectRatioChanged(newAspectRatio);
});
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 03327bf463e3..229962488acf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -725,6 +725,12 @@ public class PipTransition extends PipTransitionController implements
mPipTransitionState.getPipTaskToken());
mFinishCallback = finishCallback;
+ if (isPipClosing(info)) {
+ // If PiP is removed via a close (e.g. finishing of the activity), then
+ // clear out the PiP cache related to that activity component (e.g. reentry state).
+ mPipBoundsState.setLastPipComponentName(null /* lastPipComponentName */);
+ }
+
finishTransaction.setAlpha(pipChange.getLeash(), 0f);
if (mPendingRemoveWithFadeout) {
PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipChange.getLeash(),
@@ -952,13 +958,29 @@ public class PipTransition extends PipTransitionController implements
boolean isPipMovedToBack = info.getType() == TRANSIT_TO_BACK
&& pipChange.getMode() == TRANSIT_TO_BACK;
- boolean isPipClosed = info.getType() == TRANSIT_CLOSE
- && pipChange.getMode() == TRANSIT_CLOSE;
// If PiP is dismissed by user (i.e. via dismiss button in PiP menu)
boolean isPipDismissed = info.getType() == TRANSIT_REMOVE_PIP
&& pipChange.getMode() == TRANSIT_TO_BACK;
// PiP is being removed if the pinned task is either moved to back, closed, or dismissed.
- return isPipMovedToBack || isPipClosed || isPipDismissed;
+ return isPipMovedToBack || isPipClosing(info) || isPipDismissed;
+ }
+
+ private boolean isPipClosing(@NonNull TransitionInfo info) {
+ if (mPipTransitionState.getPipTaskToken() == null) {
+ // PiP removal makes sense if enter-PiP has cached a valid pinned task token.
+ return false;
+ }
+ TransitionInfo.Change pipChange = info.getChange(mPipTransitionState.getPipTaskToken());
+ TransitionInfo.Change pipActivityChange = info.getChanges().stream().filter(change ->
+ change.getTaskInfo() == null && change.getParent() != null
+ && change.getParent() == mPipTransitionState.getPipTaskToken())
+ .findFirst().orElse(null);
+
+ boolean isPipTaskClosed = pipChange != null
+ && pipChange.getMode() == TRANSIT_CLOSE;
+ boolean isPipActivityClosed = pipActivityChange != null
+ && pipActivityChange.getMode() == TRANSIT_CLOSE;
+ return isPipTaskClosed || isPipActivityClosed;
}
private void prepareConfigAtEndActivity(@NonNull SurfaceControl.Transaction startTx,
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 722494c05e32..2174017996a8 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
@@ -109,6 +109,7 @@ import android.util.ArraySet;
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseIntArray;
import android.view.Choreographer;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
@@ -3012,11 +3013,18 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final int transitType = info.getType();
TransitionInfo.Change pipChange = null;
int closingSplitTaskId = -1;
- // This array tracks where we are sending stages (TO_BACK/TO_FRONT) in this transition.
- // TODO (b/349828130): Update for n apps (needs to handle different indices than 0/1).
- // Also make sure having multiple changes per stage (2+ tasks in one stage) is being
- // handled properly.
- int[] stageChanges = new int[2];
+ // This array tracks if we are sending stages TO_BACK/TO_FRONT in this transition.
+ // TODO (b/349828130): Also make sure having multiple changes per stage (2+ tasks in
+ // one stage) is being handled properly.
+ SparseIntArray stageChanges = new SparseIntArray();
+ if (enableFlexibleSplit()) {
+ mStageOrderOperator.getActiveStages()
+ .forEach(stage -> stageChanges.put(stage.getId(), -1));
+ } else {
+ stageChanges.put(STAGE_TYPE_MAIN, -1);
+ stageChanges.put(STAGE_TYPE_SIDE, -1);
+ }
+
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
@@ -3090,14 +3098,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// we'll break split
closingSplitTaskId = taskId;
}
- if (transitType == WindowManager.TRANSIT_WAKE) {
- // Record which stages are receiving which changes
- if ((change.getMode() == TRANSIT_TO_BACK
- || change.getMode() == TRANSIT_TO_FRONT)
- && (stageOfTaskId == STAGE_TYPE_MAIN
- || stageOfTaskId == STAGE_TYPE_SIDE)) {
- stageChanges[stageOfTaskId] = change.getMode();
- }
+ // Record which stages are receiving which changes
+ if ((change.getMode() == TRANSIT_TO_BACK
+ || change.getMode() == TRANSIT_TO_FRONT)
+ && (stageOfTaskId == STAGE_TYPE_MAIN
+ || stageOfTaskId == STAGE_TYPE_SIDE)) {
+ stageChanges.put(getStageOfTask(taskId), change.getMode());
}
}
@@ -3126,8 +3132,16 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// If keyguard is active, check to see if we have all our stages showing. If one stage
// was moved but not the other (which can happen with SHOW_ABOVE_LOCKED apps), we should
// break split.
- if (mKeyguardActive && stageChanges[STAGE_TYPE_MAIN] != stageChanges[STAGE_TYPE_SIDE]) {
- dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
+ if (mKeyguardActive && stageChanges.size() > 0) {
+ int firstChangeMode = stageChanges.valueAt(0);
+ for (int i = 0; i < stageChanges.size(); i++) {
+ int changeMode = stageChanges.valueAt(i);
+ // Compare each changeMode to the first one. If any are different, break split.
+ if (changeMode != firstChangeMode) {
+ dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
+ break;
+ }
+ }
}
final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
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 2cf574158358..195e8195089f 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
@@ -466,7 +466,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
new DesktopModeOnTaskResizeAnimationListener());
mDesktopTasksController.setOnTaskRepositionAnimationListener(
new DesktopModeOnTaskRepositionAnimationListener());
- if (Flags.enableDesktopRecentsTransitionsCornersBugfix()) {
+ if (DesktopModeFlags.ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX.isTrue()) {
mRecentsTransitionHandler.addTransitionStateListener(
new DesktopModeRecentsTransitionStateListener());
}
@@ -1225,12 +1225,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
mDragPointerId = e.getPointerId(0);
}
final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
- // Position of the task is calculated by subtracting the raw location of the
- // motion event (the location of the motion relative to the display) by the
- // location of the motion event relative to the task's bounds
- final Point position = new Point(
- (int) (e.getRawX(dragPointerIdx) - e.getX(dragPointerIdx)),
- (int) (e.getRawY(dragPointerIdx) - e.getY(dragPointerIdx)));
final Rect newTaskBounds = mDragPositioningCallback.onDragPositioningEnd(
e.getDisplayId(),
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
@@ -1238,7 +1232,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
// DesktopTasksController to allow secondary transformations (i.e. snap resizing
// or transforming to fullscreen) before setting new task bounds.
mDesktopTasksController.onDragPositioningEnd(
- taskInfo, decoration.mTaskSurface, position,
+ taskInfo, decoration.mTaskSurface,
new PointF(e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)),
newTaskBounds, decoration.calculateValidDragArea(),
new Rect(mOnDragStartInitialBounds), e,
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 4e125d001076..b6765c477485 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
@@ -27,18 +27,17 @@ import static android.view.MotionEvent.ACTION_UP;
import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
-
import static com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode;
import static com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopModeOrShowAppHandle;
import static com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallbackUtility.DragEventListener;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.DisabledEdge;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.DisabledEdge.NONE;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeHandleEdgeInset;
-import static com.android.wm.shell.windowdecor.DragPositioningCallbackUtility.DragEventListener;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -112,14 +111,14 @@ import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
-import kotlinx.coroutines.CoroutineScope;
-import kotlinx.coroutines.MainCoroutineDispatcher;
-
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.MainCoroutineDispatcher;
+
/**
* Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
* {@link DesktopModeWindowDecorViewModel}.
@@ -579,6 +578,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
closeHandleMenu();
closeManageWindowsMenu();
closeMaximizeMenu();
+ notifyNoCaptionHandle();
}
updateDragResizeListener(oldDecorationSurface, inFullImmersive);
updateMaximizeMenu(startT, inFullImmersive);
@@ -717,7 +717,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
}
private void notifyCaptionStateChanged() {
- // TODO: b/366159408 - Ensure bounds sent with notification account for RTL mode.
if (!canEnterDesktopMode(mContext) || !isEducationEnabled()) {
return;
}
@@ -734,7 +733,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
// [AppHeaderViewHolder].
((AppHeaderViewHolder) mWindowDecorViewHolder).runOnAppChipGlobalLayout(
() -> {
- notifyAppChipStateChanged();
+ notifyAppHeaderStateChanged();
return Unit.INSTANCE;
});
}
@@ -766,7 +765,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mResult.mCaptionHeight);
}
- private void notifyAppChipStateChanged() {
+ private void notifyAppHeaderStateChanged() {
+ if (isAppHandle(mWindowDecorViewHolder) || mWindowDecorViewHolder == null) {
+ return;
+ }
final Rect appChipPositionInWindow =
((AppHeaderViewHolder) mWindowDecorViewHolder).getAppChipLocationInWindow();
final Rect taskBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
@@ -844,6 +846,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mOnCaptionButtonClickListener,
mOnCaptionLongClickListener,
mOnCaptionGenericMotionListener,
+ mOnLeftSnapClickListener,
+ mOnRightSnapClickListener,
+ mOnMaximizeOrRestoreClickListener,
mOnMaximizeHoverListener);
}
throw new IllegalArgumentException("Unexpected layout resource id");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index e5c989ed5f97..32a2f8294877 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -44,18 +44,21 @@ import android.window.SurfaceSyncGroup
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.compose.ui.graphics.toArgb
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK
import androidx.core.view.isGone
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
+import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper
import com.android.wm.shell.shared.split.SplitScreenConstants
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer
import com.android.wm.shell.windowdecor.common.DecorThemeUtil
-import com.android.wm.shell.windowdecor.common.calculateMenuPosition
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader
+import com.android.wm.shell.windowdecor.common.calculateMenuPosition
import com.android.wm.shell.windowdecor.extension.isFullscreen
import com.android.wm.shell.windowdecor.extension.isMultiWindow
import com.android.wm.shell.windowdecor.extension.isPinned
@@ -535,6 +538,20 @@ class HandleMenu(
}
return@setOnTouchListener true
}
+
+ with(context.resources) {
+ // Update a11y read out to say "double tap to enter desktop windowing mode"
+ ViewCompat.replaceAccessibilityAction(
+ desktopBtn, ACTION_CLICK,
+ getString(R.string.app_handle_menu_talkback_desktop_mode_button_text), null
+ )
+
+ // Update a11y read out to say "double tap to enter split screen mode"
+ ViewCompat.replaceAccessibilityAction(
+ splitscreenBtn, ACTION_CLICK,
+ getString(R.string.app_handle_menu_talkback_split_screen_mode_button_text), null
+ )
+ }
}
/** Binds the menu views to the new data. */
@@ -645,7 +662,7 @@ class HandleMenu(
private fun bindWindowingPill(style: MenuStyle) {
windowingPill.background.setTint(style.backgroundColor)
- if (!com.android.wm.shell.Flags.enableBubbleAnything()) {
+ if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()) {
floatingBtn.visibility = View.GONE
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
index 1ce0366728b9..be3ea4e7b71e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
@@ -34,6 +34,7 @@ import android.graphics.drawable.LayerDrawable
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.StateListDrawable
import android.graphics.drawable.shapes.RoundRectShape
+import android.os.Bundle
import android.util.StateSet
import android.view.LayoutInflater
import android.view.MotionEvent.ACTION_HOVER_ENTER
@@ -51,12 +52,16 @@ import android.view.ViewGroup
import android.view.WindowManager
import android.view.WindowlessWindowManager
import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityNodeInfo
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import android.widget.Button
import android.widget.TextView
import android.window.TaskConstants
import androidx.compose.material3.ColorScheme
import androidx.compose.ui.graphics.toArgb
import androidx.core.animation.addListener
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.android.wm.shell.R
@@ -403,6 +408,96 @@ class MaximizeMenu(
true
}
+ sizeToggleButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ if (action == AccessibilityAction.ACTION_CLICK.id) {
+ onMaximizeClickListener?.invoke()
+ }
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ snapLeftButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ if (action == AccessibilityAction.ACTION_CLICK.id) {
+ onLeftSnapClickListener?.invoke()
+ }
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ snapRightButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ if (action == AccessibilityAction.ACTION_CLICK.id) {
+ onRightSnapClickListener?.invoke()
+ }
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ with(context.resources) {
+ ViewCompat.replaceAccessibilityAction(
+ snapLeftButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_menu_talkback_action_snap_left_text),
+ null
+ )
+
+ ViewCompat.replaceAccessibilityAction(
+ snapRightButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_menu_talkback_action_snap_right_text),
+ null
+ )
+
+ ViewCompat.replaceAccessibilityAction(
+ sizeToggleButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_menu_talkback_action_maximize_restore_text),
+ null
+ )
+ }
+
// Maximize/restore button.
val sizeToggleBtnTextId = if (sizeToggleDirection == SizeToggleDirection.RESTORE)
R.string.desktop_mode_maximize_menu_restore_button_text
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt
index 70c0b54462e3..22bc9782170b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MoveToDesktopAnimator.kt
@@ -5,6 +5,7 @@ import android.app.ActivityManager.RunningTaskInfo
import android.content.Context
import android.graphics.PointF
import android.graphics.Rect
+import android.view.Choreographer
import android.view.MotionEvent
import android.view.SurfaceControl
import android.view.VelocityTracker
@@ -48,7 +49,7 @@ class MoveToDesktopAnimator @JvmOverloads constructor(
t.setScale(taskSurface, scale, scale)
.setCornerRadius(taskSurface, cornerRadius)
.setScale(taskSurface, scale, scale)
- .setCornerRadius(taskSurface, cornerRadius)
+ .setFrameTimeline(Choreographer.getInstance().vsyncId)
.setPosition(taskSurface, position.x, position.y)
.apply()
}
@@ -96,6 +97,7 @@ class MoveToDesktopAnimator @JvmOverloads constructor(
setTaskPosition(ev.rawX, ev.rawY)
val t = transactionFactory()
t.setPosition(taskSurface, position.x, position.y)
+ t.setFrameTimeline(Choreographer.getInstance().vsyncId)
t.apply()
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt
index 4fa2744b4c12..7ffa74f89a52 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt
@@ -26,6 +26,7 @@ import android.util.Size
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
+import android.view.View.LAYOUT_DIRECTION_RTL
import android.view.View.MeasureSpec.UNSPECIFIED
import android.view.WindowManager
import android.widget.ImageView
@@ -52,7 +53,6 @@ class DesktopWindowingEducationTooltipController(
private val additionalSystemViewContainerFactory: AdditionalSystemViewContainer.Factory,
private val displayController: DisplayController,
) : OnDisplayChangingListener {
- // TODO: b/369384567 - Set tooltip color scheme to match LT/DT of app theme
private var tooltipView: View? = null
private var animator: PhysicsAnimator<View>? = null
private val springConfig by lazy {
@@ -89,7 +89,7 @@ class DesktopWindowingEducationTooltipController(
}
/** Hide the current education view if visible */
- private fun hideEducationTooltip() = animateHideTooltipTransition { cleanUp() }
+ fun hideEducationTooltip() = animateHideTooltipTransition { cleanUp() }
/** Create education view by inflating layout provided. */
private fun createEducationTooltipView(
@@ -197,8 +197,9 @@ class DesktopWindowingEducationTooltipController(
background.setTint(tooltipColorScheme.container)
}
requireViewById<ImageView>(R.id.arrow_icon).apply {
- val wrappedDrawable = DrawableCompat.wrap(this.drawable)
- DrawableCompat.setTint(wrappedDrawable, tooltipColorScheme.container)
+ val wrappedDrawable = DrawableCompat.wrap(this.drawable)
+ DrawableCompat.setTint(wrappedDrawable, tooltipColorScheme.container)
+ if (isRtl()) scaleX = -1f
}
requireViewById<TextView>(R.id.tooltip_text).apply { setTextColor(tooltipColorScheme.text) }
requireViewById<ImageView>(R.id.tooltip_icon).apply {
@@ -227,6 +228,9 @@ class DesktopWindowingEducationTooltipController(
// Arrow is placed at vertical center on the left edge of the tooltip. Hence decrement
// half of tooltip height from [tooltipY] to vertically position the tooltip.
tooltipY -= tooltipDimen.height / 2
+ if (isRtl()) {
+ tooltipX -= tooltipDimen.width
+ }
}
return Point(tooltipX, tooltipY)
}
@@ -260,7 +264,9 @@ class DesktopWindowingEducationTooltipController(
return context.resources.getDimensionPixelSize(resourceId)
}
- /**
+ private fun isRtl() = context.resources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
+
+ /**
* The configuration for education view features:
*
* @property tooltipViewLayout Layout resource ID of the view to be used for education tooltip.
@@ -297,6 +303,6 @@ class DesktopWindowingEducationTooltipController(
/** Direction of arrow of the tooltip */
enum class TooltipArrowDirection {
UP,
- LEFT,
+ HORIZONTAL
}
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
index 9f8ca7740182..db12f899f42f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
@@ -27,10 +27,13 @@ import android.graphics.drawable.LayerDrawable
import android.graphics.drawable.RippleDrawable
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RoundRectShape
+import android.os.Bundle
import android.view.View
import android.view.View.OnLongClickListener
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityNodeInfo
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
@@ -49,6 +52,8 @@ import com.android.internal.R.color.materialColorSurfaceDim
import com.android.window.flags.Flags
import com.android.wm.shell.R
import android.window.DesktopModeFlags
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
import com.android.wm.shell.windowdecor.MaximizeButtonView
import com.android.wm.shell.windowdecor.common.DecorThemeUtil
import com.android.wm.shell.windowdecor.common.OPACITY_100
@@ -71,7 +76,10 @@ class AppHeaderViewHolder(
onCaptionButtonClickListener: View.OnClickListener,
private val onLongClickListener: OnLongClickListener,
onCaptionGenericMotionListener: View.OnGenericMotionListener,
- onMaximizeHoverAnimationFinishedListener: () -> Unit
+ mOnLeftSnapClickListener: () -> Unit,
+ mOnRightSnapClickListener: () -> Unit,
+ mOnMaximizeOrRestoreClickListener: () -> Unit,
+ onMaximizeHoverAnimationFinishedListener: () -> Unit,
) : WindowDecorationViewHolder<AppHeaderViewHolder.HeaderData>(rootView) {
data class HeaderData(
@@ -153,6 +161,91 @@ class AppHeaderViewHolder(
minimizeWindowButton.setOnTouchListener(onCaptionTouchListener)
maximizeButtonView.onHoverAnimationFinishedListener =
onMaximizeHoverAnimationFinishedListener
+
+ val a11yActionSnapLeft = AccessibilityAction(
+ R.id.action_snap_left,
+ context.resources.getString(R.string.desktop_mode_a11y_action_snap_left)
+ )
+ val a11yActionSnapRight = AccessibilityAction(
+ R.id.action_snap_right,
+ context.resources.getString(R.string.desktop_mode_a11y_action_snap_right)
+ )
+ val a11yActionMaximizeRestore = AccessibilityAction(
+ R.id.action_maximize_restore,
+ context.resources.getString(R.string.desktop_mode_a11y_action_maximize_restore)
+ )
+
+ captionHandle.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(a11yActionSnapLeft)
+ info.addAction(a11yActionSnapRight)
+ info.addAction(a11yActionMaximizeRestore)
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ when (action) {
+ R.id.action_snap_left -> mOnLeftSnapClickListener.invoke()
+ R.id.action_snap_right -> mOnRightSnapClickListener.invoke()
+ R.id.action_maximize_restore -> mOnMaximizeOrRestoreClickListener.invoke()
+ }
+
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+ maximizeWindowButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ info.addAction(a11yActionSnapLeft)
+ info.addAction(a11yActionSnapRight)
+ info.addAction(a11yActionMaximizeRestore)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ when (action) {
+ AccessibilityAction.ACTION_CLICK.id -> host.performClick()
+ R.id.action_snap_left -> mOnLeftSnapClickListener.invoke()
+ R.id.action_snap_right -> mOnRightSnapClickListener.invoke()
+ R.id.action_maximize_restore -> mOnMaximizeOrRestoreClickListener.invoke()
+ }
+
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ with(context.resources) {
+ // Update a11y read out to say "double tap to maximize or restore window size"
+ ViewCompat.replaceAccessibilityAction(
+ maximizeWindowButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_button_talkback_action_maximize_restore_text),
+ null
+ )
+
+ // Update a11y read out to say "double tap to minimize app window"
+ ViewCompat.replaceAccessibilityAction(
+ minimizeWindowButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.minimize_button_talkback_action_maximize_restore_text),
+ null
+ )
+ }
}
override fun bindData(data: HeaderData) {
@@ -628,6 +721,9 @@ class AppHeaderViewHolder(
onCaptionButtonClickListener: View.OnClickListener,
onLongClickListener: OnLongClickListener,
onCaptionGenericMotionListener: View.OnGenericMotionListener,
+ mOnLeftSnapClickListener: () -> Unit,
+ mOnRightSnapClickListener: () -> Unit,
+ mOnMaximizeOrRestoreClickListener: () -> Unit,
onMaximizeHoverAnimationFinishedListener: () -> Unit,
): AppHeaderViewHolder = AppHeaderViewHolder(
rootView,
@@ -635,6 +731,9 @@ class AppHeaderViewHolder(
onCaptionButtonClickListener,
onLongClickListener,
onCaptionGenericMotionListener,
+ mOnLeftSnapClickListener,
+ mOnRightSnapClickListener,
+ mOnMaximizeOrRestoreClickListener,
onMaximizeHoverAnimationFinishedListener,
)
}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeMouse.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeMouse.kt
index c3abf238dc0d..ff0a9d5f80f9 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeMouse.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeMouse.kt
@@ -34,18 +34,6 @@ class ResizeAppWithEdgeResizeMouse : ResizeAppWithEdgeResize(InputMethod.MOUSE)
@Test
override fun resizeAppWithEdgeResizeRight() = super.resizeAppWithEdgeResizeRight()
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeLeft() = super.resizeAppWithEdgeResizeLeft()
-
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeTop() = super.resizeAppWithEdgeResizeTop()
-
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeBottom() = super.resizeAppWithEdgeResizeBottom()
-
companion object {
@JvmStatic
@FlickerConfigProvider
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeStylus.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeStylus.kt
index 86b0e6f17b24..73a4753ac9ed 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeStylus.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeStylus.kt
@@ -34,18 +34,6 @@ class ResizeAppWithEdgeResizeStylus : ResizeAppWithEdgeResize(InputMethod.STYLUS
@Test
override fun resizeAppWithEdgeResizeRight() = super.resizeAppWithEdgeResizeRight()
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeLeft() = super.resizeAppWithEdgeResizeLeft()
-
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeTop() = super.resizeAppWithEdgeResizeTop()
-
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeBottom() = super.resizeAppWithEdgeResizeBottom()
-
companion object {
@JvmStatic
@FlickerConfigProvider
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeTouchpad.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeTouchpad.kt
index e6bb9eff6715..f81c1611b22c 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeTouchpad.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppWithEdgeResizeTouchpad.kt
@@ -34,18 +34,6 @@ class ResizeAppWithEdgeResizeTouchpad : ResizeAppWithEdgeResize(InputMethod.TOUC
@Test
override fun resizeAppWithEdgeResizeRight() = super.resizeAppWithEdgeResizeRight()
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeLeft() = super.resizeAppWithEdgeResizeLeft()
-
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeTop() = super.resizeAppWithEdgeResizeTop()
-
- @ExpectedScenarios(["EDGE_RESIZE"])
- @Test
- override fun resizeAppWithEdgeResizeBottom() = super.resizeAppWithEdgeResizeBottom()
-
companion object {
@JvmStatic
@FlickerConfigProvider
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
index f198cfed7c50..1dfa6acc5124 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
@@ -72,33 +72,6 @@ constructor(
)
}
- @Test
- open fun resizeAppWithEdgeResizeLeft() {
- testApp.edgeResize(
- wmHelper,
- motionEventHelper,
- DesktopModeAppHelper.Edges.LEFT
- )
- }
-
- @Test
- open fun resizeAppWithEdgeResizeTop() {
- testApp.edgeResize(
- wmHelper,
- motionEventHelper,
- DesktopModeAppHelper.Edges.TOP
- )
- }
-
- @Test
- open fun resizeAppWithEdgeResizeBottom() {
- testApp.edgeResize(
- wmHelper,
- motionEventHelper,
- DesktopModeAppHelper.Edges.BOTTOM
- )
- }
-
@After
fun teardown() {
testApp.exit(wmHelper)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
index 372e47ce6a17..f61ea4a194d6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
@@ -42,7 +42,6 @@ import android.window.TransitionInfo
import android.window.WindowContainerToken
import android.window.WindowContainerTransaction
import androidx.test.filters.SmallTest
-import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE
import com.android.internal.jank.InteractionJankMonitor
import com.android.window.flags.Flags
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
@@ -143,10 +142,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @DisableFlags(
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX,
- )
+ @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX)
fun startRemoveTransition_callsFreeformTaskTransitionHandler() {
val wct = WindowContainerTransaction()
whenever(freeformTaskTransitionHandler.startRemoveTransition(wct)).thenReturn(mock())
@@ -157,10 +153,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX)
fun startRemoveTransition_startsCloseTransition() {
val wct = WindowContainerTransaction()
whenever(transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, mixedHandler))
@@ -200,10 +193,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX)
fun startAnimation_withClosingDesktopTask_callsCloseTaskHandler() {
val wct = WindowContainerTransaction()
val transition = mock<IBinder>()
@@ -231,10 +221,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX)
fun startAnimation_withClosingLastDesktopTask_dispatchesTransition() {
val wct = WindowContainerTransaction()
val transition = mock<IBinder>()
@@ -266,19 +253,11 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
any(),
eq(mixedHandler),
)
- verify(interactionJankMonitor)
- .begin(
- closingTaskLeash,
- context,
- mockHandler,
- CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE,
- )
}
@Test
@DisableFlags(
Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP,
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
)
fun startLaunchTransition_immersiveAndAppLaunchFlagsDisabled_doesNotUseMixedHandler() {
@@ -316,10 +295,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
fun startLaunchTransition_desktopAppLaunchEnabled_usesMixedHandler() {
val wct = WindowContainerTransaction()
val task = createTask(WINDOWING_MODE_FREEFORM)
@@ -415,10 +391,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
fun startAndAnimateLaunchTransition_noMinimizeChange_doesNotReparentMinimizeChange() {
val wct = WindowContainerTransaction()
val launchingTask = createTask(WINDOWING_MODE_FREEFORM)
@@ -444,10 +417,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
fun startAndAnimateLaunchTransition_withMinimizeChange_reparentsMinimizeChange() {
val wct = WindowContainerTransaction()
val launchingTask = createTask(WINDOWING_MODE_FREEFORM)
@@ -476,10 +446,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
fun startAnimation_pendingTransition_noLaunchChange_returnsFalse() {
val wct = WindowContainerTransaction()
val launchingTask = createTask(WINDOWING_MODE_FREEFORM)
@@ -569,10 +536,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
fun addPendingAndAnimateLaunchTransition_noMinimizeChange_doesNotReparentMinimizeChange() {
val wct = WindowContainerTransaction()
val launchingTask = createTask(WINDOWING_MODE_FREEFORM)
@@ -600,10 +564,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
- @EnableFlags(
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
- Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
- )
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
fun addPendingAndAnimateLaunchTransition_withMinimizeChange_reparentsMinimizeChange() {
val wct = WindowContainerTransaction()
val launchingTask = createTask(WINDOWING_MODE_FREEFORM)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 40c0e3610da2..a139f1670181 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -1624,6 +1624,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER)
fun moveToFullscreen_tdaFullscreen_windowingModeUndefined_removesWallpaperActivity() {
+ whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true)
+ val homeTask = setUpHomeTask()
val task = setUpFreeformTask()
assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
.configuration
@@ -1637,9 +1639,33 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
verify(desktopModeEnterExitTransitionListener)
.onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION)
assertThat(taskChange.windowingMode).isEqualTo(WINDOWING_MODE_UNDEFINED)
- assertThat(wct.hierarchyOps).hasSize(1)
+ assertThat(wct.hierarchyOps).hasSize(3)
// Removes wallpaper activity when leaving desktop
wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
+ // Moves home task behind the fullscreen task
+ wct.assertReorderAt(index = 1, homeTask.getToken(), toTop = true)
+ wct.assertReorderAt(index = 2, task.getToken(), toTop = true)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER)
+ fun moveToFullscreen_tdaFreeform_enforcedDesktop_doesNotReorderHome() {
+ whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true)
+ val homeTask = setUpHomeTask()
+ val task = setUpFreeformTask()
+ assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
+ .configuration
+ .windowConfiguration
+ .windowingMode = WINDOWING_MODE_FREEFORM
+
+ controller.moveToFullscreen(task.taskId, transitionSource = UNKNOWN)
+
+ val wct = getLatestExitDesktopWct()
+ verify(desktopModeEnterExitTransitionListener)
+ .onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION)
+ assertThat(wct.hierarchyOps).hasSize(1)
+ // Removes wallpaper activity when leaving desktop but doesn't reorder home or the task
+ wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
}
@Test
@@ -1658,6 +1684,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER)
fun moveToFullscreen_tdaFreeform_windowingModeFullscreen_removesWallpaperActivity() {
+ val homeTask = setUpHomeTask()
val task = setUpFreeformTask()
assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
@@ -1672,13 +1699,17 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
assertThat(taskChange.windowingMode).isEqualTo(WINDOWING_MODE_FULLSCREEN)
verify(desktopModeEnterExitTransitionListener)
.onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION)
- assertThat(wct.hierarchyOps).hasSize(1)
+ assertThat(wct.hierarchyOps).hasSize(3)
// Removes wallpaper activity when leaving desktop
wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
+ // Moves home task behind the fullscreen task
+ wct.assertReorderAt(index = 1, homeTask.getToken(), toTop = true)
+ wct.assertReorderAt(index = 2, task.getToken(), toTop = true)
}
@Test
fun moveToFullscreen_multipleVisibleNonMinimizedTasks_doesNotRemoveWallpaperActivity() {
+ val homeTask = setUpHomeTask()
val task1 = setUpFreeformTask()
// Setup task2
setUpFreeformTask()
@@ -1696,7 +1727,10 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
verify(desktopModeEnterExitTransitionListener)
.onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION)
// Does not remove wallpaper activity, as desktop still has a visible desktop task
- assertThat(wct.hierarchyOps).isEmpty()
+ assertThat(wct.hierarchyOps).hasSize(2)
+ // Moves home task behind the fullscreen task
+ wct.assertReorderAt(index = 0, homeTask.getToken(), toTop = true)
+ wct.assertReorderAt(index = 1, task1.getToken(), toTop = true)
}
@Test
@@ -3421,6 +3455,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
fun moveFocusedTaskToFullscreen_multipleVisibleTasks_doesNotRemoveWallpaperActivity() {
+ val homeTask = setUpHomeTask()
val task1 = setUpFreeformTask()
val task2 = setUpFreeformTask()
val task3 = setUpFreeformTask()
@@ -3435,7 +3470,10 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
assertThat(taskChange.windowingMode)
.isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
// Does not remove wallpaper activity, as desktop still has visible desktop tasks
- assertThat(wct.hierarchyOps).isEmpty()
+ assertThat(wct.hierarchyOps).hasSize(2)
+ // Moves home task behind the fullscreen task
+ wct.assertReorderAt(index = 0, homeTask.getToken(), toTop = true)
+ wct.assertReorderAt(index = 1, task2.getToken(), toTop = true)
}
@Test
@@ -3707,7 +3745,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
spyController.onDragPositioningEnd(
task,
mockSurface,
- position = Point(100, -100),
inputCoordinate = PointF(200f, -200f),
currentDragBounds = Rect(100, -100, 500, 1000),
validDragArea = Rect(0, 50, 2000, 2000),
@@ -3746,7 +3783,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
spyController.onDragPositioningEnd(
task,
mockSurface,
- position = Point(100, 200),
inputCoordinate = PointF(200f, 300f),
currentDragBounds = currentDragBounds,
validDragArea = Rect(0, 50, 2000, 2000),
@@ -3787,7 +3823,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
spyController.onDragPositioningEnd(
task,
mockSurface,
- position = Point(100, 200),
inputCoordinate = PointF(200f, 300f),
currentDragBounds,
validDragArea = Rect(0, 50, 2000, 2000),
@@ -3829,7 +3864,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
spyController.onDragPositioningEnd(
task,
mockSurface,
- position = Point(100, 50),
inputCoordinate = PointF(200f, 300f),
currentDragBounds = Rect(100, 50, 500, 1000),
validDragArea = Rect(0, 50, 2000, 2000),
@@ -3868,7 +3902,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
spyController.onDragPositioningEnd(
task,
mockSurface,
- position = Point(100, 50),
inputCoordinate = PointF(200f, 300f),
currentDragBounds,
validDragArea = Rect(0, 50, 2000, 2000),
@@ -3925,7 +3958,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
spyController.onDragPositioningEnd(
task,
mockSurface,
- position = Point(100, 50),
inputCoordinate = PointF(200f, 300f),
currentDragBounds = currentDragBounds,
validDragArea = Rect(0, 50, 2000, 2000),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
index 493a8c83c48e..1160a9286572 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
@@ -29,6 +29,7 @@ import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.CaptionState
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository
import com.android.wm.shell.desktopmode.education.AppHandleEducationController.Companion.APP_HANDLE_EDUCATION_DELAY_MILLIS
+import com.android.wm.shell.desktopmode.education.AppHandleEducationController.Companion.TOOLTIP_VISIBLE_DURATION_MILLIS
import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource
@@ -128,6 +129,23 @@ class AppHandleEducationControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
+ fun init_appHandleEducationVisible_afterDelayTooltipShouldBeDismissed() =
+ testScope.runTest {
+ // App handle is visible. Should show education tooltip.
+ setShouldShowDesktopModeEducation(true)
+ // Simulate app handle visible.
+ testCaptionStateFlow.value = createAppHandleState()
+ // Wait for first tooltip to showup.
+ waitForBufferDelay()
+
+ // Wait until tooltip gets dismissed
+ waitForBufferDelay(TOOLTIP_VISIBLE_DURATION_MILLIS + 1000L)
+
+ verify(mockTooltipController, times(1)).hideEducationTooltip()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
fun init_appHandleVisibleAndMenuExpanded_shouldCallShowEducationTooltipAndMarkAsViewed() =
testScope.runTest {
setShouldShowDesktopModeEducation(true)
@@ -157,6 +175,64 @@ class AppHandleEducationControllerTest : ShellTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
+ fun init_noCaptionStateNotified_shouldHideAllTooltips() =
+ testScope.runTest {
+ setShouldShowDesktopModeEducation(true)
+
+ // Simulate no caption state notification
+ testCaptionStateFlow.value = CaptionState.NoCaption
+ waitForBufferDelay()
+
+ verify(mockTooltipController, times(1)).hideEducationTooltip()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
+ fun init_appHandleHintViewed_shouldNotListenToNoCaptionNotification() =
+ testScope.runTest {
+ testDataStoreFlow.value =
+ createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L)
+ setShouldShowDesktopModeEducation(true)
+
+ // Simulate no caption state notification
+ testCaptionStateFlow.value = CaptionState.NoCaption
+ waitForBufferDelay()
+
+ verify(mockTooltipController, never()).hideEducationTooltip()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
+ fun init_enterDesktopModeHintViewed_shouldNotListenToNoCaptionNotification() =
+ testScope.runTest {
+ testDataStoreFlow.value =
+ createWindowingEducationProto(enterDesktopModeHintViewedTimestampMillis = 123L)
+ setShouldShowDesktopModeEducation(true)
+
+ // Simulate no caption state notification
+ testCaptionStateFlow.value = CaptionState.NoCaption
+ waitForBufferDelay()
+
+ verify(mockTooltipController, never()).hideEducationTooltip()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
+ fun init_exitDesktopModeHintViewed_shouldNotListenToNoCaptionNotification() =
+ testScope.runTest {
+ testDataStoreFlow.value =
+ createWindowingEducationProto(exitDesktopModeHintViewedTimestampMillis = 123L)
+ setShouldShowDesktopModeEducation(true)
+
+ // Simulate no caption state notification
+ testCaptionStateFlow.value = CaptionState.NoCaption
+ waitForBufferDelay()
+
+ verify(mockTooltipController, never()).hideEducationTooltip()
+ }
+
+ @Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION)
fun init_flagDisabled_shouldNotCallShowEducationTooltip() =
testScope.runTest {
@@ -271,8 +347,7 @@ class AppHandleEducationControllerTest : ShellTestCase() {
// Mark app handle hint viewed.
testDataStoreFlow.value =
createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L)
- val systemPropertiesKey = "persist.windowing_force_show_desktop_mode_education"
- whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean()))
+ whenever(SystemProperties.getBoolean(eq(FORCE_SHOW_EDUCATION_SYSPROP), anyBoolean()))
.thenReturn(true)
setShouldShowDesktopModeEducation(true)
@@ -368,13 +443,17 @@ class AppHandleEducationControllerTest : ShellTestCase() {
* Class under test waits for some time before showing education, simulate advance time before
* verifying or moving forward
*/
- private fun TestScope.waitForBufferDelay() {
- advanceTimeBy(APP_HANDLE_EDUCATION_DELAY_BUFFER_MILLIS)
+ private fun TestScope.waitForBufferDelay(
+ delay: Long = APP_HANDLE_EDUCATION_DELAY_BUFFER_MILLIS
+ ) {
+ advanceTimeBy(delay)
runCurrent()
}
private companion object {
val APP_HANDLE_EDUCATION_DELAY_BUFFER_MILLIS: Long =
APP_HANDLE_EDUCATION_DELAY_MILLIS + 1000L
+
+ val FORCE_SHOW_EDUCATION_SYSPROP = "persist.windowing_force_show_desktop_mode_education"
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
index 89cb729d17b5..3923a1ef5633 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.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.when;
import static org.mockito.kotlin.MatchersKt.eq;
@@ -193,6 +194,12 @@ public class PipTaskListenerTest {
mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
mMockPipBoundsAlgorithm, mMockShellExecutor);
mPipTaskListener.addParamsChangedListener(mMockPipParamsChangedCallback);
+
+ // For this test case, any aspect ratio passed is considered within allowed range.
+ when(mMockPipBoundsAlgorithm
+ .isValidPictureInPictureAspectRatio(anyFloat()))
+ .thenReturn(true);
+
Rational aspectRatio = new Rational(4, 3);
when(mMockPipBoundsState.getAspectRatio()).thenReturn(aspectRatio.toFloat());
String action1 = "action1";
@@ -227,6 +234,29 @@ public class PipTaskListenerTest {
}
@Test
+ public void onTaskInfoChanged_nonValidAspectRatio_doesNotCallbackAspectRatioChanged() {
+ mPipTaskListener = new PipTaskListener(mMockContext, mMockShellTaskOrganizer,
+ mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
+ mMockPipBoundsAlgorithm, mMockShellExecutor);
+ mPipTaskListener.addParamsChangedListener(mMockPipParamsChangedCallback);
+
+ String action1 = "action1";
+ mPipTaskListener.onTaskInfoChanged(getTaskInfo(null, action1));
+ verify(mMockPipTransitionState, times(0))
+ .setOnIdlePipTransitionStateRunnable(any(Runnable.class));
+
+ // Define an invalid aspect ratio and try and update the params with it.
+ Rational aspectRatio = new Rational(100, 3);
+ when(mMockPipBoundsAlgorithm
+ .isValidPictureInPictureAspectRatio(eq(aspectRatio.floatValue())))
+ .thenReturn(false);
+
+ mPipTaskListener.onTaskInfoChanged(getTaskInfo(aspectRatio, action1));
+ verify(mMockPipTransitionState, times(0))
+ .setOnIdlePipTransitionStateRunnable(any(Runnable.class));
+ }
+
+ @Test
public void onPipTransitionStateChanged_scheduledBoundsChangeWithAspectRatioChange_schedule() {
mPipTaskListener = new PipTaskListener(mMockContext, mMockShellTaskOrganizer,
mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/WindowAnimatorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/WindowAnimatorTest.kt
index c19232b6f787..4630649c75cc 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/WindowAnimatorTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/animation/WindowAnimatorTest.kt
@@ -31,6 +31,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.anyLong
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
@@ -56,6 +57,7 @@ class WindowAnimatorTest {
whenever(change.endAbsBounds).thenReturn(END_BOUNDS)
whenever(transaction.setPosition(any(), anyFloat(), anyFloat())).thenReturn(transaction)
whenever(transaction.setScale(any(), anyFloat(), anyFloat())).thenReturn(transaction)
+ whenever(transaction.setFrameTimeline(anyLong())).thenReturn(transaction)
whenever(
transaction.setPosition(
any(),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 87198d14c839..76e1e805f5a9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -297,7 +297,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
.thenReturn(mMockHandleMenu);
when(mMockMultiInstanceHelper.supportsMultiInstanceSplit(any(), anyInt()))
.thenReturn(false);
- when(mMockAppHeaderViewHolderFactory.create(any(), any(), any(), any(), any(), any()))
+ when(mMockAppHeaderViewHolderFactory
+ .create(any(), any(), any(), any(), any(), any(), any(), any(), any()))
.thenReturn(mMockAppHeaderViewHolder);
when(mMockDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
when(mMockDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt
index 15f2c7be38b7..3134b18af491 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt
@@ -154,12 +154,12 @@ class DesktopWindowingEducationTooltipControllerTest : ShellTestCase() {
}
@Test
- fun showEducationTooltip_tooltipPointsLeft_verticallyPositionTooltip() {
+ fun showEducationTooltip_tooltipPointsHorizontally_verticallyPositionTooltip() {
val initialTooltipX = 0
val initialTooltipY = 0
val tooltipViewConfig =
createTooltipConfig(
- arrowDirection = TooltipArrowDirection.LEFT,
+ arrowDirection = TooltipArrowDirection.HORIZONTAL,
tooltipViewGlobalCoordinates = Point(initialTooltipX, initialTooltipY))
val tooltipYArgumentCaptor = argumentCaptor<Int>()
val tooltipHeightArgumentCaptor = argumentCaptor<Int>()
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 8bc66a048d27..f308ce953680 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -18,6 +18,7 @@ package android.media;
import static android.media.audio.Flags.FLAG_DOLBY_AC4_LEVEL4_ENCODING_API;
import static android.media.audio.Flags.FLAG_IAMF_DEFINITIONS_API;
+import static android.media.audio.Flags.FLAG_SONY_360RA_MPEGH_3D_FORMAT;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
@@ -718,8 +719,9 @@ public final class AudioFormat implements Parcelable {
* Same as 9.1.4 with the addition of left and right top side channels */
public static final int CHANNEL_OUT_9POINT1POINT6 = (CHANNEL_OUT_9POINT1POINT4
| CHANNEL_OUT_TOP_SIDE_LEFT | CHANNEL_OUT_TOP_SIDE_RIGHT);
- /** @hide */
- public static final int CHANNEL_OUT_13POINT_360RA = (
+ /** Output channel mask for 13.0 */
+ @FlaggedApi(FLAG_SONY_360RA_MPEGH_3D_FORMAT)
+ public static final int CHANNEL_OUT_13POINT0 = (
CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
CHANNEL_OUT_TOP_FRONT_LEFT | CHANNEL_OUT_TOP_FRONT_CENTER |
@@ -915,7 +917,7 @@ public final class AudioFormat implements Parcelable {
case CHANNEL_OUT_9POINT1POINT6:
result.append("9.1.6");
break;
- case CHANNEL_OUT_13POINT_360RA:
+ case CHANNEL_OUT_13POINT0:
result.append("360RA 13ch");
break;
case CHANNEL_OUT_22POINT2:
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index 8cc42e0bd9b5..b6096a1acd85 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -15,4 +15,5 @@ per-file ExifInterface.java,ExifInterfaceUtils.java,IMediaHTTPConnection.aidl,IM
# Haptics team also works on Ringtone
per-file *Ringtone* = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file flags/media_better_together.aconfig = file:platform/frameworks/av:/media/janitors/better_together_OWNERS
per-file flags/projection.aconfig = file:projection/OWNERS
diff --git a/media/java/android/media/audio/common/AidlConversion.java b/media/java/android/media/audio/common/AidlConversion.java
index 8521d1c472a8..b831e4f83e02 100644
--- a/media/java/android/media/audio/common/AidlConversion.java
+++ b/media/java/android/media/audio/common/AidlConversion.java
@@ -366,8 +366,8 @@ public class AidlConversion {
return AudioFormat.CHANNEL_OUT_9POINT1POINT4;
case AudioChannelLayout.LAYOUT_9POINT1POINT6:
return AudioFormat.CHANNEL_OUT_9POINT1POINT6;
- case AudioChannelLayout.LAYOUT_13POINT_360RA:
- return AudioFormat.CHANNEL_OUT_13POINT_360RA;
+ case AudioChannelLayout.LAYOUT_13POINT0:
+ return AudioFormat.CHANNEL_OUT_13POINT0;
case AudioChannelLayout.LAYOUT_22POINT2:
return AudioFormat.CHANNEL_OUT_22POINT2;
case AudioChannelLayout.LAYOUT_MONO_HAPTIC_A:
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 28f238ece47a..0dd8d1907829 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -80,7 +81,8 @@ public class AudioEffect {
private final static String TAG = "AudioEffect-JAVA";
- // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h
+ // effect type UUIDs are taken
+ // from hardware/interfaces/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
/**
* The following UUIDs define effect types corresponding to standard audio
@@ -148,6 +150,16 @@ public class AudioEffect {
.fromString("7261676f-6d75-7369-6364-28e2fd3ac39e");
/**
+ * @hide
+ * UUID for the Spatializer effect
+ */
+ @SuppressLint("UnflaggedApi") // Test API
+ @TestApi
+ @NonNull
+ public static final UUID EFFECT_TYPE_SPATIALIZER =
+ UUID.fromString("ccd4cf09-a79d-46c2-9aae-06a1698d6c8f");
+
+ /**
* UUID for Haptic Generator.
*/
// This is taken from system/media/audio/include/system/audio_effects/effect_hapticgenerator.h
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index ec336d5efee6..cf8e391533f6 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -126,30 +126,6 @@ public class CameraBinderTest extends AndroidTestCase {
}
}
- /** The camera2 api is only supported on HAL3.2+ devices */
- @SmallTest
- public void testSupportsCamera2Api() throws Exception {
- for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- boolean supports = mUtils.getCameraService().supportsCameraApi(
- String.valueOf(cameraId), API_VERSION_2);
-
- Log.v(TAG, "Camera " + cameraId + " supports api2: " + supports);
- }
- }
-
- /** The camera1 api is supported on *all* devices regardless of HAL version */
- @SmallTest
- public void testSupportsCamera1Api() throws Exception {
- for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
-
- boolean supports = mUtils.getCameraService().supportsCameraApi(
- String.valueOf(cameraId), API_VERSION_1);
- assertTrue(
- "Camera service returned false when queried if it supports camera1 api " +
- " for camera ID " + cameraId, supports);
- }
- }
-
static abstract class DummyBase extends Binder implements android.os.IInterface {
@Override
public IBinder asBinder() {
diff --git a/packages/ExtShared/Android.bp b/packages/ExtShared/Android.bp
index b1fd7f64292d..58016f78782a 100644
--- a/packages/ExtShared/Android.bp
+++ b/packages/ExtShared/Android.bp
@@ -38,6 +38,7 @@ android_app {
aaptflags: ["--shared-lib"],
export_package_resources: true,
optimize: {
+ keep_runtime_invisible_annotations: true,
proguard_flags_files: ["proguard.proguard"],
},
}
diff --git a/packages/ExtShared/proguard.proguard b/packages/ExtShared/proguard.proguard
index e5dfbe1c453d..699fbdaaadad 100644
--- a/packages/ExtShared/proguard.proguard
+++ b/packages/ExtShared/proguard.proguard
@@ -1,6 +1,8 @@
-keepparameternames
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
- SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
+ SourceFile,LineNumberTable,EnclosingMethod,
+ RuntimeVisibleAnnotations,RuntimeVisibleParameterAnnotations,
+ RuntimeVisibleTypeAnnotations,AnnotationDefault
-keep public class * {
public protected *;
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
index eaf5bcd8c3b7..30ed347fc0bd 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
@@ -21,7 +21,7 @@
<string name="menu_show_system" msgid="906304605807554788">"نمایش سیستم"</string>
<string name="menu_hide_system" msgid="374571689914923020">"پنهان کردن سیستم"</string>
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"مجاز"</string>
- <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"مجاز نبودن"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"غیرمجاز"</string>
<string name="version_text" msgid="4001669804596458577">"نسخه <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
<string name="cloned_app_info_label" msgid="1765651167024478391">"همسانه <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/TopIntroPreference/res/layout/settingslib_expressive_top_intro.xml b/packages/SettingsLib/TopIntroPreference/res/layout/settingslib_expressive_top_intro.xml
index 834814ccbc6b..1c6b1ebd1535 100644
--- a/packages/SettingsLib/TopIntroPreference/res/layout/settingslib_expressive_top_intro.xml
+++ b/packages/SettingsLib/TopIntroPreference/res/layout/settingslib_expressive_top_intro.xml
@@ -18,7 +18,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart">
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:filterTouchesWhenObscured="true">
<com.android.settingslib.widget.CollapsableTextView
android:id="@+id/collapsable_text_view"
diff --git a/packages/SettingsLib/res/drawable/dialog_btn_filled.xml b/packages/SettingsLib/res/drawable/dialog_btn_filled.xml
index 0614f9dbff8c..b4577d19ac6b 100644
--- a/packages/SettingsLib/res/drawable/dialog_btn_filled.xml
+++ b/packages/SettingsLib/res/drawable/dialog_btn_filled.xml
@@ -28,7 +28,7 @@
<item>
<shape android:shape="rectangle">
<corners android:radius="@dimen/button_corner_radius"/>
- <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+ <solid android:color="?androidprv:attr/colorAccent"/>
<padding android:left="@dimen/dialog_button_horizontal_padding"
android:top="@dimen/dialog_button_vertical_padding"
android:right="@dimen/dialog_button_horizontal_padding"
diff --git a/packages/SettingsLib/res/drawable/dialog_btn_outline.xml b/packages/SettingsLib/res/drawable/dialog_btn_outline.xml
index a920b50585ae..a15891c714d3 100644
--- a/packages/SettingsLib/res/drawable/dialog_btn_outline.xml
+++ b/packages/SettingsLib/res/drawable/dialog_btn_outline.xml
@@ -29,7 +29,7 @@
<shape android:shape="rectangle">
<corners android:radius="@dimen/button_corner_radius"/>
<solid android:color="@android:color/transparent"/>
- <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant"
+ <stroke android:color="?androidprv:attr/colorAccent"
android:width="1dp"/>
<padding android:left="@dimen/dialog_button_horizontal_padding"
android:top="@dimen/dialog_button_vertical_padding"
diff --git a/packages/SettingsLib/res/layout/dialog_with_icon.xml b/packages/SettingsLib/res/layout/dialog_with_icon.xml
index b21895b31256..1c542910214a 100644
--- a/packages/SettingsLib/res/layout/dialog_with_icon.xml
+++ b/packages/SettingsLib/res/layout/dialog_with_icon.xml
@@ -16,6 +16,7 @@
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/new_user_dialog_id">
@@ -30,6 +31,7 @@
android:id="@+id/dialog_with_icon_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:tint="?androidprv:attr/colorAccent"
android:importantForAccessibility="no"/>
<TextView
android:id="@+id/dialog_with_icon_title"
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index ae95613df96d..bb38f8f103c4 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -301,10 +301,10 @@
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Mostrar dispositivos Bluetooth sin nombre"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Inhabilitar volumen absoluto"</string>
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Habilitar Gabeldorsche"</string>
- <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión de AVRCP del Bluetooth"</string>
- <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versión de AVRCP del Bluetooth"</string>
- <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de MAP de Bluetooth"</string>
- <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Seleccionar versión de MAP de Bluetooth"</string>
+ <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión AVRCP del Bluetooth"</string>
+ <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versión AVRCP del Bluetooth"</string>
+ <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión MAP del Bluetooth"</string>
+ <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Seleccionar versión MAP del Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec del audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo del audio Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 9ed48b1c013d..0628ba37e02e 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -424,7 +424,7 @@
<string name="transition_animation_scale_title" msgid="1278477690695439337">"Ülemineku animatsioonimastaap"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"Animaatori kestuse mastaap"</string>
<string name="overlay_display_devices_title" msgid="5411894622334469607">"Modelleeri teisi ekraane"</string>
- <string name="shade_display_awareness_title" msgid="8000009404669495876">"Menüü kuvamise asukoht"</string>
+ <string name="shade_display_awareness_title" msgid="8000009404669495876">"Varju kuvamise asukoht"</string>
<string name="debug_applications_category" msgid="5394089406638954196">"Rakendused"</string>
<string name="immediately_destroy_activities" msgid="1826287490705167403">"Ära hoia tegevusi alles"</string>
<string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Hävita kõik tegevused kohe, kui kasutaja neist lahkub"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 24dafa92ede6..b257dd160325 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -569,7 +569,7 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta gogorarazpenak"</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, gogorarazpena, erlojua"</string>
- <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"Ez molestatzeko"</string>
+ <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"Ez molestatzeko modua"</string>
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ez molestatzeko modua"</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-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index bfe68feb5c98..9b8f6277410b 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -672,16 +672,16 @@
<string name="grant_admin" msgid="4323199171790522574">"હા, તેમને ઍડમિન બનાવો"</string>
<string name="not_grant_admin" msgid="3557849576157702485">"ના, તેમને ઍડમિન બનાવશો નહીં"</string>
<string name="guest_exit_dialog_button" msgid="1736401897067442044">"બહાર નીકળો"</string>
- <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"શું અતિથિ પ્રવૃત્તિ સાચવીએ?"</string>
- <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"તમે હાલના સત્રની પ્રવૃત્તિ સાચવી શકો છો અથવા તમામ ઍપ અને ડેટા ડિલીટ કરી શકો છો"</string>
+ <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"શું અતિથિની ઍક્ટિવિટીને સાચવીએ?"</string>
+ <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"તમે હાલના સત્રની ઍક્ટિવિટીને સાચવી શકો છો અથવા તમામ ઍપ અને ડેટા ડિલીટ કરી શકો છો"</string>
<string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ડિલીટ કરો"</string>
<string name="guest_exit_save_data_button" msgid="3690974510644963547">"સાચવો"</string>
<string name="guest_exit_button" msgid="5774985819191803960">"અતિથિ મોડમાંથી બહાર નીકળો"</string>
<string name="guest_reset_button" msgid="2515069346223503479">"અતિથિ સત્ર રીસેટ કરો"</string>
<string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"અતિથિ મોડમાંથી બહાર નીકળો"</string>
<string name="guest_notification_ephemeral" msgid="7263252466950923871">"બહાર નીકળતી વખતે તમામ ઍક્ટિવિટી ડિલીટ કરવામાં આવશે"</string>
- <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"બહાર નીકળતી વખતે તમે પ્રવૃત્તિ સાચવી કે ડિલીટ કરી શકશો"</string>
- <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"સત્રની પ્રવૃત્તિ હમણાં ડિલીટ કરવા માટે રીસેટ કરો અથવા બહાર નીકળતી વખતે તમે પ્રવૃત્તિ સાચવી કે ડિલીટ કરી શકશો"</string>
+ <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"બહાર નીકળતી વખતે તમે ઍક્ટિવિટીને સાચવી કે ડિલીટ કરી શકશો"</string>
+ <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"સત્રની ઍક્ટિવિટીને હમણાં ડિલીટ કરવા માટે, રીસેટ કરો. અથવા બહાર નીકળતી વખતે તમે ઍક્ટિવિટીને સાચવી કે ડિલીટ કરી શકશો"</string>
<string name="user_image_photo_selector" msgid="433658323306627093">"ફોટો પસંદ કરો"</string>
<string name="failed_attempts_now_wiping_device" msgid="4016329172216428897">"ઘણા બધા ખોટા પ્રયત્નો. આ ડિવાઇસનો ડેટા ડિલીટ કરવામાં આવશે."</string>
<string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"ઘણા બધા ખોટા પ્રયત્નો. આ વપરાશકર્તાને ડિલીટ કરવામાં આવશે."</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 5146ebc75e81..1923a72e8898 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -250,7 +250,7 @@
<string name="enable_adb" msgid="8072776357237289039">"यूएसबी डीबग करना"</string>
<string name="enable_adb_summary" msgid="3711526030096574316">"डीबग मोड जब यूएसबी कनेक्‍ट किया गया हो"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"यूएसबी डीबग करने की अनुमति रद्द करें"</string>
- <string name="enable_adb_wireless" msgid="6973226350963971018">"वॉयरलेस डीबगिंग"</string>
+ <string name="enable_adb_wireless" msgid="6973226350963971018">"वायरलेस डीबगिंग"</string>
<string name="enable_adb_wireless_summary" msgid="7344391423657093011">"डिवाइस के वाई-फ़ाई से कनेक्ट हाेने पर, डीबग मोड चालू करें"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"गड़बड़ी"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"वॉयरलेस डीबगिंग"</string>
@@ -665,8 +665,8 @@
<string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"रीसेट करें"</string>
<string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"हटाएं"</string>
<string name="guest_resetting" msgid="7822120170191509566">"मेहमान के तौर पर ब्राउज़ करने का सेशन रीसेट किया जा रहा है…"</string>
- <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"क्या मेहमान मोड के मौजूदा सेशन को रीसेट करना है?"</string>
- <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"इससे मेहमान के तौर पर ब्राउज़ करने का नया सेशन शुरू हो जाएगा. इसके अलावा, इस्तेमाल किए जा रहे ऐप्लिकेशन पर की गई गतिविधि और मौजूदा सेशन का डेटा मिटा दिया जाएगा"</string>
+ <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"क्या मेहमान उपयोगकर्ता के मौजूदा सेशन को रीसेट करना है?"</string>
+ <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"इससे मेहमान के तौर पर ब्राउज़ करने का नया सेशन शुरू हो जाएगा. इसके अलावा, मौजूदा सेशन में डाउनलोड किए गए ऐप्लिकेशन और सेव किया गया सारा डेटा मिट जाएगा"</string>
<string name="guest_exit_dialog_title" msgid="1846494656849381804">"मेहमान मोड से बाहर निकलना है?"</string>
<string name="guest_exit_dialog_message" msgid="1743218864242719783">"इससे, मेहमान मोड के मौजूदा सेशन का डेटा और इसमें इस्तेमाल हो रहे ऐप्लिकेशन मिट जाएंगे"</string>
<string name="grant_admin" msgid="4323199171790522574">"हां, इन्हें एडमिन बनाएं"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index d1771fcfffec..5c1845f6dca9 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -296,7 +296,7 @@
<string-array name="shade_display_awareness_summaries">
<item msgid="2964753205732912921">"הצגת הצללה במסך המכשיר בלבד"</item>
<item msgid="7795034287069726554">"הצגת המכשיר במסך חיצוני אחד"</item>
- <item msgid="5280431949814340475">"הצגת המכשיר במסך האחרון שהתמקדת בו"</item>
+ <item msgid="5280431949814340475">"הצגת ההתראות במסך האחרון שהשתמשת בו"</item>
</string-array>
<string-array name="shade_display_awareness_values">
<item msgid="3055776101992426514">"default_display"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index bf039adf35e9..be26f71621c4 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -424,7 +424,7 @@
<string name="transition_animation_scale_title" msgid="1278477690695439337">"קנה מידה לאנימציית מעבר"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"קנה מידה למשך זמן אנימציה"</string>
<string name="overlay_display_devices_title" msgid="5411894622334469607">"יצירת הדמיה של תצוגות משניות"</string>
- <string name="shade_display_awareness_title" msgid="8000009404669495876">"מיקום התצוגה של ההצללה"</string>
+ <string name="shade_display_awareness_title" msgid="8000009404669495876">"מיקום לוח ההתראות"</string>
<string name="debug_applications_category" msgid="5394089406638954196">"אפליקציות"</string>
<string name="immediately_destroy_activities" msgid="1826287490705167403">"ללא שמירת פעילויות"</string>
<string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"השמדת כל פעילות ברגע שהמשתמש עוזב אותה"</string>
@@ -681,7 +681,7 @@
<string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"יציאה ממצב אורח"</string>
<string name="guest_notification_ephemeral" msgid="7263252466950923871">"כל הפעילות תימחק ביציאה"</string>
<string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"אפשר לשמור או למחוק את הפעילות שלך ביציאה"</string>
- <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ניתן לאפס כדי למחוק את הפעילות מהסשן כעת, או לשמור או למחוק את הפעילות ביציאה"</string>
+ <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"אפשר לאפס כדי למחוק עכשיו את הפעילות מהסשן, או לשמור או למחוק את הפעילות ביציאה"</string>
<string name="user_image_photo_selector" msgid="433658323306627093">"בחירת תמונה"</string>
<string name="failed_attempts_now_wiping_device" msgid="4016329172216428897">"נעשו יותר מדי ניסיונות שגויים. הנתונים במכשיר יימחקו."</string>
<string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"נעשו יותר מדי ניסיונות שגויים. המשתמש הזה יימחק."</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 08dfa7d1a600..a1ab4f3b8671 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -690,7 +690,7 @@
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Төхөөрөмжийн өгөгдмөл"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Идэвхгүй болгосон"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Идэвхжүүлсэн"</string>
- <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Энэ өөрчлөлтийг хэрэгжүүлэхийн тулд таны төхөөрөмжийг дахин асаах ёстой. Одоо дахин асаах эсвэл цуцлана уу."</string>
+ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Энэ өөрчлөлтийг хэрэгжүүлэхийн тулд таны төхөөрөмжийг дахин асаах ёстой. Одоо дахин асаах эсвэл цуцална уу."</string>
<string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Утастай чихэвч"</string>
<string name="media_transfer_headphone_name" msgid="1157798825650178478">"Утастай аудио"</string>
<string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB аудио"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 3f88af62f8c7..1af92867b9ab 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -666,14 +666,14 @@
<string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"काढून टाका"</string>
<string name="guest_resetting" msgid="7822120170191509566">"अतिथीला रीसेट करत आहे…"</string>
<string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"अतिथी सत्र रीसेट करायचे का?"</string>
- <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"हे नवीन अतिथी सत्र सुरू करेल आणि सध्याच्या सत्रातील सर्व अ‍ॅप्स व डेटा हटवेल"</string>
+ <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"हे नवीन अतिथी सत्र सुरू करेल आणि सद्य सत्रातील सर्व अ‍ॅप्स व डेटा हटवेल"</string>
<string name="guest_exit_dialog_title" msgid="1846494656849381804">"अतिथी मोडमधून बाहेर पडायचे का?"</string>
<string name="guest_exit_dialog_message" msgid="1743218864242719783">"हे सध्याच्या अतिथी सत्रातील अ‍ॅप्स आणि डेटा हटवेल"</string>
<string name="grant_admin" msgid="4323199171790522574">"होय, त्यांना ॲडमिन करा"</string>
<string name="not_grant_admin" msgid="3557849576157702485">"नाही, त्यांना ॲडमिन करू नका"</string>
<string name="guest_exit_dialog_button" msgid="1736401897067442044">"बाहेर पडा"</string>
<string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"अतिथी अ‍ॅक्टिव्हिटी सेव्ह करायची का?"</string>
- <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"सध्याच्या सत्रातील अ‍ॅक्टिव्हिटी सेव्ह करू किंवा सर्व अ‍ॅप्स व डेटा हटवू शकता"</string>
+ <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"सद्य सत्रातील अ‍ॅक्टिव्हिटी सेव्ह करू शकता किंवा सर्व अ‍ॅप्स व डेटा हटवू शकता"</string>
<string name="guest_exit_clear_data_button" msgid="3425812652180679014">"हटवा"</string>
<string name="guest_exit_save_data_button" msgid="3690974510644963547">"सेव्ह करा"</string>
<string name="guest_exit_button" msgid="5774985819191803960">"अतिथी मोडमधून बाहेर पडा"</string>
@@ -727,7 +727,7 @@
<string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट डिस्कनेक्ट केले."</string>
<string name="accessibility_ethernet_connected" msgid="6175942685957461563">"इथरनेट."</string>
<string name="accessibility_no_calling" msgid="3540827068323895748">"कॉलिंग उपलब्ध नाही."</string>
- <string name="physical_keyboard_title" msgid="4811935435315835220">"वास्तविक कीबोर्ड"</string>
+ <string name="physical_keyboard_title" msgid="4811935435315835220">"प्रत्यक्ष कीबोर्ड"</string>
<string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"किबोर्ड लेआउट निवडा"</string>
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"डीफॉल्ट"</string>
<string name="turn_screen_on_title" msgid="2662312432042116026">"स्क्रीन सुरू करण्यासंबंधित नियंत्रण"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 9525884488a5..4a31a1216325 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -424,7 +424,7 @@
<string name="transition_animation_scale_title" msgid="1278477690695439337">"သက်ဝင်အသွင်ပြောင်းခြင်း"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"လှုပ်ရှားမှုကြာချိန်စကေး"</string>
<string name="overlay_display_devices_title" msgid="5411894622334469607">"ဆင့်ပွားမျက်နှာပြင် အသွင်ဆောင်ခြင်း"</string>
- <string name="shade_display_awareness_title" msgid="8000009404669495876">"အရိပ်ပြကွက် တည်နေရာ"</string>
+ <string name="shade_display_awareness_title" msgid="8000009404669495876">"အကြောင်းကြားချက်ပြကွက် နေရာ"</string>
<string name="debug_applications_category" msgid="5394089406638954196">"အက်ပ်များ"</string>
<string name="immediately_destroy_activities" msgid="1826287490705167403">"ဆောင်ရွက်မှုများကို သိမ်းမထားပါနှင့်"</string>
<string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"သုံးသူထွက်သွားသည်နှင့် လုပ်ဆောင်ချက်များ ဖျက်ရန်"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 803309c890b8..869d9a1d1757 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -615,7 +615,7 @@
<string name="help_label" msgid="3528360748637781274">"ସାହାଯ୍ୟ ଓ ମତାମତ"</string>
<string name="storage_category" msgid="2287342585424631813">"ଷ୍ଟୋରେଜ"</string>
<string name="shared_data_title" msgid="1017034836800864953">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ଦେଖନ୍ତୁ ଏବଂ ଏହାକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"ସେୟାର ହୋଇଥିବା ଡାଟା ଭ୍ୟୁ କରନ୍ତୁ ଏବଂ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ କୌଣସି ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ନାହିଁ।"</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ଫେଚ୍ କରିବା ସମୟରେ ଏକ ତ୍ରୁଟି ହୋଇଥିଲା। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="blob_id_text" msgid="8680078988996308061">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index d8726db136bd..6c0ce86a6f8e 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -680,8 +680,8 @@
<string name="guest_reset_button" msgid="2515069346223503479">"ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਨੂੰ ਰੀਸੈੱਟ ਕਰੋ"</string>
<string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ਮਹਿਮਾਨ ਮੋਡ ਤੋਂ ਬਾਹਰ ਜਾਓ"</string>
<string name="guest_notification_ephemeral" msgid="7263252466950923871">"ਬਾਹਰ ਜਾਣ \'ਤੇ ਸਾਰੀ ਸਰਗਰਮੀ ਮਿਟਾ ਦਿੱਤੀ ਜਾਵੇਗੀ"</string>
- <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ਤੁਸੀਂ ਬਾਹਰ ਜਾਣ \'ਤੇ ਆਪਣੀ ਸਰਗਰਮੀ ਰੱਖਿਅਤ ਕਰ ਜਾਂ ਮਿਟਾ ਸਕਦੇ ਹੋ"</string>
- <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ਸੈਸ਼ਨ ਦੀ ਸਰਗਰਮੀ ਹੁਣੇ ਮਿਟਾਉਣ ਲਈ ਰੀਸੈੱਟ ਕਰੋ ਜਾਂ ਤੁਸੀਂ ਬਾਹਰ ਜਾਣ \'ਤੇ ਸਰਗਰਮੀ ਨੂੰ ਰੱਖਿਅਤ ਕਰ ਜਾਂ ਮਿਟਾ ਸਕਦੇ ਹੋ"</string>
+ <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ਤੁਸੀਂ ਬਾਹਰ ਜਾਣ ਸਮੇਂ ਆਪਣੀ ਸਰਗਰਮੀ ਰੱਖਿਅਤ ਕਰ ਜਾਂ ਮਿਟਾ ਸਕਦੇ ਹੋ"</string>
+ <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ਸੈਸ਼ਨ ਦੀ ਸਰਗਰਮੀ ਹੁਣੇ ਮਿਟਾਉਣ ਲਈ ਰੀਸੈੱਟ ਕਰੋ ਜਾਂ ਤੁਸੀਂ ਬਾਹਰ ਜਾਣ ਸਮੇਂ ਸਰਗਰਮੀ ਨੂੰ ਰੱਖਿਅਤ ਕਰ ਜਾਂ ਮਿਟਾ ਸਕਦੇ ਹੋ"</string>
<string name="user_image_photo_selector" msgid="433658323306627093">"ਫ਼ੋਟੋ ਚੁਣੋ"</string>
<string name="failed_attempts_now_wiping_device" msgid="4016329172216428897">"ਬਹੁਤ ਸਾਰੀਆਂ ਗਲਤ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਸ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
<string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"ਬਹੁਤ ਸਾਰੀਆਂ ਗਲਤ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 2f870bfac3d8..2829f20722f7 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -296,7 +296,7 @@
<string-array name="shade_display_awareness_summaries">
<item msgid="2964753205732912921">"Mostrar a sombra apenas no ecrã do dispositivo"</item>
<item msgid="7795034287069726554">"Mostrar o dispositivo num único ecrã externo"</item>
- <item msgid="5280431949814340475">"Mostrar o dispositivo no último ecrã focado"</item>
+ <item msgid="5280431949814340475">"Apresente o dispositivo no último ecrã focado"</item>
</string-array>
<string-array name="shade_display_awareness_values">
<item msgid="3055776101992426514">"default_display"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 9d56b4330985..457aacdcee14 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -251,7 +251,7 @@
<string name="enable_adb_summary" msgid="3711526030096574316">"Modo de depuração com USB ligado"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"Revogar autorizações de depur. USB"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"Depuração sem fios"</string>
- <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando o Wi-Fi está ligado"</string>
+ <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração com Wi-Fi ligado"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Erro."</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração sem fios"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e utilizar dispositivos disponíveis, ative a depuração sem fios."</string>
@@ -279,7 +279,7 @@
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Estabeleça ligação a uma rede Wi-Fi."</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depurar, programador"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de erro"</string>
- <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão no menu ligar/desligar para criar um relatório de erro"</string>
+ <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Acrescente um botão ao menu ligar/desligar para criar um relatório de erro"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Manter ativo"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"O ecrã nunca entrará em suspensão durante o carregamento"</string>
<string name="bt_hci_snoop_log" msgid="7291287955649081448">"Ativar registo de monitorização Bluetooth HCI"</string>
@@ -288,8 +288,8 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Permitir o desbloqueio do carregador de arranque"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Permitir o desbloqueio de OEM?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"AVISO: as funcionalidades de proteção do dispositivo não funcionam neste dispositivo enquanto esta definição estiver ativada."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Selecionar app de localização fictícia"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"Aplicação de localização fictícia não definida"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Selecionar app de localização de teste"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"App de localização de teste não definida"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"Aplicação de localização fictícia: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Redes"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"Certificação de display sem fios"</string>
@@ -359,7 +359,7 @@
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Ativar aplicação terminal que oferece acesso local à shell"</string>
<string name="enable_linux_terminal_title" msgid="5076044866895670637">"Ambiente de programação Linux"</string>
- <string name="enable_linux_terminal_summary" msgid="2029479880888108902">"(Experimental) Executar terminal do Linux no Android"</string>
+ <string name="enable_linux_terminal_summary" msgid="2029479880888108902">"(Experimental) Execute o terminal do Linux no Android"</string>
<string name="disable_linux_terminal_disclaimer" msgid="3054320531778388231">"Se desativar a app, os dados do terminal do Linux são limpos"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Verificação HDCP"</string>
<string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"Definir o comportamento da verificação HDCP"</string>
@@ -412,19 +412,19 @@
<string name="track_frame_time" msgid="522674651937771106">"Renderização HWUI do perfil"</string>
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar camadas de depuração GPU"</string>
<string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite carregamento de camadas de depuração de GPU para apps de depuração"</string>
- <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Ativ. registo do fornecedor"</string>
- <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Inclua registos adicionais de fornecedores específicos de dispositivos em relatórios de erros, que podem conter informações privadas, utilizar mais bateria e/ou utilizar mais armazenamento."</string>
+ <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Ativar registo verboso de fornecedor"</string>
+ <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Inclua registos adicionais de fornecedores específicos de dispositivos em relatórios de erro, que podem conter informações privadas, usar mais bateria e/ou mais armazenamento."</string>
<string name="enable_verbose_vendor_logging_checkbox" msgid="3864578373293835530">"Desativar após um dia"</string>
<string name="verbose_vendor_logging_notification_title" msgid="6811217272559843592">"O registo verboso de fornecedor terminou"</string>
<string name="verbose_vendor_logging_notification_summary" msgid="5226524769774370942">"Ativado durante um dia"</string>
<string name="verbose_vendor_logging_notification_action" msgid="1190831050259046071">"Ativar durante mais um dia"</string>
<string name="verbose_vendor_logging_preference_summary_will_disable" msgid="6175431593394522553">"É desativado após um dia"</string>
<string name="verbose_vendor_logging_preference_summary_on" msgid="9017757242481762036">"Ativado indefinidamente"</string>
- <string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animação de transição"</string>
+ <string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animação de janelas"</string>
<string name="transition_animation_scale_title" msgid="1278477690695439337">"Escala de animação de transição"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"Escala de duração de animação"</string>
- <string name="overlay_display_devices_title" msgid="5411894622334469607">"Simular apresentações secundárias"</string>
- <string name="shade_display_awareness_title" msgid="8000009404669495876">"Posição da sombra no ecrã"</string>
+ <string name="overlay_display_devices_title" msgid="5411894622334469607">"Simular ecrãs secundários"</string>
+ <string name="shade_display_awareness_title" msgid="8000009404669495876">"Posição do painel no ecrã"</string>
<string name="debug_applications_category" msgid="5394089406638954196">"Apps"</string>
<string name="immediately_destroy_activities" msgid="1826287490705167403">"Não manter atividades"</string>
<string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Destruir atividades assim que o utilizador sair"</string>
@@ -615,7 +615,7 @@
<string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
<string name="storage_category" msgid="2287342585424631813">"Armazenamento"</string>
<string name="shared_data_title" msgid="1017034836800864953">"Dados partilhados"</string>
- <string name="shared_data_summary" msgid="5516326713822885652">"Ver e modificar dados partilhados"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Veja e modifique dados partilhados"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Não existem dados partilhados para este utilizador."</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"Ocorreu um erro ao obter os dados partilhados. Tente novamente."</string>
<string name="blob_id_text" msgid="8680078988996308061">"ID de dados partilhados: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index c66242beee37..49d520eda21c 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -288,9 +288,9 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Tillåt att bootloadern låses upp"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Vill du tillåta OEM-upplåsning?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"Varning! Funktionerna för enhetsskydd fungerar inte på enheten när den här inställningen är aktiverad."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Välj app för påhittad plats"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"Ingen app för påhittad plats har angetts"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"App för påhittad plats: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Välj app för simulerad plats"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"Ingen app för simulerad plats har angetts"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"App för simulerad plats: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Nätverk"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"Certifiering för wifi-skärmdelning"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktivera utförlig loggning för wifi"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index c18d771e9399..8dea6ed2d013 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -296,7 +296,7 @@
<string-array name="shade_display_awareness_summaries">
<item msgid="2964753205732912921">"షేడ్‌ను పరికర డిస్‌ప్లేలో మాత్రమే చూపండి"</item>
<item msgid="7795034287069726554">"పరికరాన్ని ఒక ఎక్స్‌టర్నల్ డిస్‌ప్లేలో మాత్రమే చూపండి"</item>
- <item msgid="5280431949814340475">"పరికరాన్ని ఫోకస్ చేసిన చివరి డిస్‌ప్లేలో మాత్రమే చూపండి"</item>
+ <item msgid="5280431949814340475">"పరికరాన్ని చివరగా యాక్టివ్‌గా ఉన్న స్క్రీన్‌లో చూపండి"</item>
</string-array>
<string-array name="shade_display_awareness_values">
<item msgid="3055776101992426514">"default_display"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index aae20b22e30f..d0b76341c7d5 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -358,7 +358,7 @@
<string name="enhanced_connectivity_summary" msgid="1576414159820676330">"మెరుగైన కనెక్టివిటీ ఫీచర్‌ను ఎనేబుల్ చేస్తుంది."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"స్థానిక టెర్మినల్"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"స్థానిక షెల్ యాక్సెస్‌ను అందించే టెర్మినల్ యాప్‌ను ప్రారంభించండి"</string>
- <string name="enable_linux_terminal_title" msgid="5076044866895670637">"Linux డెవలప్మెంట్ ఎన్విరాన్మెంట్"</string>
+ <string name="enable_linux_terminal_title" msgid="5076044866895670637">"Linux డెవలప్‌మెంట్ ఎన్విరాన్‌మెంట్"</string>
<string name="enable_linux_terminal_summary" msgid="2029479880888108902">"(ప్రయోగాత్మకం) Linux టెర్మినల్‌ను Androidలో రన్ చేయండి"</string>
<string name="disable_linux_terminal_disclaimer" msgid="3054320531778388231">"మీరు డిజేబుల్ చేస్తే, Linux టెర్మినల్ డేటా క్లియర్ అవుతుంది"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP చెకింగ్‌"</string>
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 1249c6b71b55..3326b6034237 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -94,7 +94,7 @@
<style name="DialogButtonPositive">
<item name="android:background">@drawable/dialog_btn_filled</item>
- <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
+ <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
<item name="android:textSize">14sp</item>
<item name="android:lineHeight">20sp</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
index e3d7902f34b2..00973811dbf0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/ActionDisabledByAdminControllerFactory.java
@@ -84,7 +84,11 @@ public final class ActionDisabledByAdminControllerFactory {
return false;
}
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
- return ParentalControlsUtilsInternal.parentConsentRequired(context, dpm,
+ final SupervisionManager sm =
+ android.app.supervision.flags.Flags.deprecateDpmSupervisionApis()
+ ? context.getSystemService(SupervisionManager.class)
+ : null;
+ return ParentalControlsUtilsInternal.parentConsentRequired(context, dpm, sm,
BiometricAuthenticator.TYPE_ANY_BIOMETRIC, new UserHandle(UserHandle.myUserId()));
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java b/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java
index 4cf3bc23b9a0..6e64c597f5cc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/CustomDialogHelper.java
@@ -173,6 +173,11 @@ public class CustomDialogHelper {
* //TODO: modify method to allow setting state for any button.
*/
public CustomDialogHelper setButtonEnabled(boolean enabled) {
+ if (enabled) {
+ mPositiveButton.setAlpha(1f);
+ } else {
+ mPositiveButton.setAlpha(0.5f);
+ }
mPositiveButton.setEnabled(enabled);
return this;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index c47bf628002d..7c588b3834a5 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4072,7 +4072,7 @@ public class SettingsProvider extends ContentProvider {
@VisibleForTesting
final class UpgradeController {
- private static final int SETTINGS_VERSION = 226;
+ private static final int SETTINGS_VERSION = 227;
private final int mUserId;
@@ -6266,6 +6266,51 @@ public class SettingsProvider extends ContentProvider {
currentVersion = 226;
}
+ // Version 226: Introduces dreaming while postured setting and migrates user from
+ // docked dream trigger to postured dream trigger.
+ if (currentVersion == 226) {
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting dreamOnDock = secureSettings.getSettingLocked(
+ Secure.SCREENSAVER_ACTIVATE_ON_DOCK);
+ final Setting dreamsEnabled = secureSettings.getSettingLocked(
+ Secure.SCREENSAVER_ENABLED);
+ final boolean dreamOnPosturedDefault = getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsActivatedOnPosturedByDefault);
+ final boolean dreamsEnabledByDefault = getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsEnabledByDefault);
+
+ if (dreamOnPosturedDefault && !dreamOnDock.isNull()
+ && dreamOnDock.getValue().equals("1")) {
+ // Disable dock activation and enable postured.
+ secureSettings.insertSettingOverrideableByRestoreLocked(
+ Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+ "0",
+ null,
+ true,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ secureSettings.insertSettingOverrideableByRestoreLocked(
+ Secure.SCREENSAVER_ACTIVATE_ON_POSTURED,
+ "1",
+ null,
+ true,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+
+ // Disable dreams overall, so user doesn't start to unexpectedly see dreams
+ // enabled when postured.
+ if (!dreamsEnabledByDefault && !dreamsEnabled.isNull()
+ && dreamsEnabled.getValue().equals("1")) {
+ secureSettings.insertSettingOverrideableByRestoreLocked(
+ Secure.SCREENSAVER_ENABLED,
+ "0",
+ null,
+ true,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+
+ currentVersion = 227;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java b/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java
index 5ce97eb22a04..292aa51db18f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java
@@ -34,6 +34,8 @@ final class WritableNamespaces {
public static final Set<String> ALLOWLIST =
new ArraySet<String>(Arrays.asList(
"adservices",
+ "autofill",
+ "app_compat_overrides",
"captive_portal_login",
"connectivity",
"exo",
diff --git a/packages/Shell/Android.bp b/packages/Shell/Android.bp
index 5fdf0451d2c8..c0c19129d79f 100644
--- a/packages/Shell/Android.bp
+++ b/packages/Shell/Android.bp
@@ -29,6 +29,7 @@ android_app {
"device_policy_aconfig_flags_lib",
],
flags_packages: [
+ "android.companion.virtualdevice.flags-aconfig",
"android.security.flags-aconfig",
"android.permission.flags-aconfig",
"wear_aconfig_declarations",
@@ -55,6 +56,7 @@ android_library {
platform_apis: true,
manifest: "AndroidManifest.xml",
flags_packages: [
+ "android.companion.virtualdevice.flags-aconfig",
"android.security.flags-aconfig",
"android.permission.flags-aconfig",
],
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a044738d2e91..2b4e65f2415c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -969,6 +969,13 @@
<uses-permission android:name="android.permission.MANAGE_INTRUSION_DETECTION_STATE"
android:featureFlag="android.security.afl_api"/>
+ <!-- Permissions required for CTS test - CtsVirtualDevicesTestCases -->
+ <uses-permission android:name="android.permission.ASSOCIATE_COMPANION_DEVICES" />
+ <uses-permission android:name="android.permission.CREATE_VIRTUAL_DEVICE" />
+ <uses-permission android:name="android.permission.ADD_TRUSTED_DISPLAY" />
+ <uses-permission android:name="android.permission.ADD_ALWAYS_UNLOCKED_DISPLAY" />
+ <uses-permission android:name="android.permission.ADD_MIRROR_DISPLAY"
+ android:featureFlag="android.companion.virtualdevice.flags.enable_limited_vdm_role"/>
<!-- Permission required for CTS test - CtsAppTestCases -->
<uses-permission android:name="android.permission.KILL_UID" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 6491bf5c8f5b..72ae76a45cac 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1171,5 +1171,16 @@
android:exported="false"
/>
+ <service
+ android:name="com.google.android.systemui.lowlightclock.LowLightClockDreamService"
+ android:enabled="false"
+ android:exported="false"
+ android:directBootAware="true"
+ android:permission="android.permission.BIND_DREAM_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.dreams.DreamService" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </service>
</application>
</manifest>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml
index 1e28bff6ca7e..817ef0cfdaca 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-nl/strings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="accessibility_menu_service_name" msgid="730136711554740131">"toegankelijkheids­menu"</string>
+ <string name="accessibility_menu_service_name" msgid="730136711554740131">"Toegankelijkheids­menu"</string>
<string name="accessibility_menu_intro" msgid="3164193281544042394">"Het toegankelijkheidsmenu is een groot menu op het scherm waarmee je je apparaat kunt bedienen. Je kunt onder meer je apparaat vergrendelen, het volume en de helderheid aanpassen en screenshots maken."</string>
<string name="assistant_label" msgid="6796392082252272356">"Assistent"</string>
<string name="assistant_utterance" msgid="65509599221141377">"Assistent"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rBR/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rBR/strings.xml
index f12278a15a8b..2afa2aa413fb 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt-rBR/strings.xml
@@ -21,7 +21,7 @@
<string name="previous_button_content_description" msgid="840869171117765966">"Ir para tela anterior"</string>
<string name="next_button_content_description" msgid="6810058269847364406">"Ir para a próxima tela"</string>
<string name="accessibility_menu_description" msgid="4458354794093858297">"\"Acessibilidade\" é um grande menu mostrado na tela para controlar seu dispositivo. Você pode bloquear o dispositivo, controlar o volume e o brilho, fazer capturas de tela e muito mais."</string>
- <string name="accessibility_menu_summary" msgid="340071398148208130">"Controlar o dispositivo com o menu grande"</string>
+ <string name="accessibility_menu_summary" msgid="340071398148208130">"Controle o dispositivo com o menu grande"</string>
<string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Config. do menu de acessibilidade"</string>
<string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Botões grandes"</string>
<string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Aumentar o tamanho dos botões do menu de acessibilidade"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt/strings.xml
index f12278a15a8b..2afa2aa413fb 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-pt/strings.xml
@@ -21,7 +21,7 @@
<string name="previous_button_content_description" msgid="840869171117765966">"Ir para tela anterior"</string>
<string name="next_button_content_description" msgid="6810058269847364406">"Ir para a próxima tela"</string>
<string name="accessibility_menu_description" msgid="4458354794093858297">"\"Acessibilidade\" é um grande menu mostrado na tela para controlar seu dispositivo. Você pode bloquear o dispositivo, controlar o volume e o brilho, fazer capturas de tela e muito mais."</string>
- <string name="accessibility_menu_summary" msgid="340071398148208130">"Controlar o dispositivo com o menu grande"</string>
+ <string name="accessibility_menu_summary" msgid="340071398148208130">"Controle o dispositivo com o menu grande"</string>
<string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Config. do menu de acessibilidade"</string>
<string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Botões grandes"</string>
<string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Aumentar o tamanho dos botões do menu de acessibilidade"</string>
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index a92df8026715..dace50fafbf1 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -541,6 +541,16 @@ flag {
}
flag {
+ name: "face_scanning_animation_npe_fix"
+ namespace: "systemui"
+ description: "Fix for the face scanning animation NPE"
+ bug: "392032258"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "indication_text_a11y_fix"
namespace: "systemui"
description: "add double shadow to the indication text at the bottom of the lock screen"
@@ -623,13 +633,6 @@ flag {
}
flag {
- name: "quick_settings_visual_haptics_longpress"
- namespace: "systemui"
- description: "Enable special visual and haptic effects for quick settings tiles with long-press actions"
- bug: "229856884"
-}
-
-flag {
name: "switch_user_on_bg"
namespace: "systemui"
description: "Does user switching on a background thread"
@@ -1204,6 +1207,13 @@ flag {
}
flag {
+ name: "glanceable_hub_blurred_background"
+ namespace: "systemui"
+ description: "Allow blurred background on glanceable hub"
+ bug: "389788272"
+}
+
+flag {
name: "communal_widget_resizing"
namespace: "systemui"
description: "Allow resizing of widgets on glanceable hub"
@@ -1325,10 +1335,13 @@ flag {
}
flag {
- name: "media_controls_drawables_reuse"
+ name: "media_controls_drawables_reuse_bugfix"
namespace: "systemui"
description: "Re-use created media drawables for media controls"
bug: "358402034"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
@@ -1949,13 +1962,10 @@ flag {
}
flag {
- name: "magnetic_notification_horizontal_swipe"
+ name: "magnetic_notification_swipes"
namespace: "systemui"
description: "Add support for magnetic behavior on horizontal notification swipes."
bug: "390179908"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
}
flag {
@@ -1998,3 +2008,10 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "show_locked_by_your_watch_keyguard_indicator"
+ namespace: "systemui"
+ description: "Show a Locked by your watch indicator on the keyguard when the device is locked by the watch."
+ bug: "387322459"
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java
index f36f0306d82b..694fc8eb6ad7 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationRunnerCompat.java
@@ -22,7 +22,6 @@ import static android.view.WindowManager.TRANSIT_OLD_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
-import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS;
import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -165,8 +164,7 @@ public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner
t.show(wallpapers[i].leash);
t.setAlpha(wallpapers[i].leash, 1.f);
}
- if (ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue()
- || ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX.isTrue()) {
+ if (ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX.isTrue()) {
resetLauncherAlphaOnDesktopExit(info, launcherTask, leashMap, t);
}
} else {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 824f5a28b4d1..3ffbabb09710 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -256,6 +256,7 @@ fun ContentScope.CommunalScene(
CommunalBackgroundType.STATIC_GRADIENT -> StaticLinearGradient()
CommunalBackgroundType.ANIMATED -> AnimatedLinearGradient()
CommunalBackgroundType.NONE -> BackgroundTopScrim()
+ CommunalBackgroundType.BLUR -> Background()
}
with(content) {
@@ -314,6 +315,9 @@ private fun BoxScope.BackgroundTopScrim() {
Box(Modifier.matchParentSize().alpha(0.34f).background(scrimOnTopColor))
}
+/** Transparent (nothing) composable for when the background is blurred. */
+@Composable private fun BoxScope.Background() {}
+
/** The duration to use for the gradient background animation. */
private const val ANIMATION_DURATION_MS = 10_000
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index 25b673bee1cd..f0d3f3e3f0a5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -142,6 +142,7 @@ fun FooterActions(
mutableStateOf<FooterActionsForegroundServicesButtonViewModel?>(null)
}
var userSwitcher by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) }
+ var power by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) }
LaunchedEffect(
context,
@@ -161,6 +162,7 @@ fun FooterActions(
launch { viewModel.security.collect { security = it } }
launch { viewModel.foregroundServices.collect { foregroundServices = it } }
launch { viewModel.userSwitcher.collect { userSwitcher = it } }
+ launch { viewModel.power.collect { power = it } }
}
}
@@ -220,7 +222,7 @@ fun FooterActions(
foregroundServices?.let { ForegroundServicesButton(it) }
userSwitcher?.let { IconButton(it, Modifier.sysuiResTag("multi_user_switch")) }
IconButton(viewModel.settings, Modifier.sysuiResTag("settings_button_container"))
- viewModel.power?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
+ power?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index d7545cb07849..22556777c40f 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -26,7 +26,6 @@ import com.android.systemui.scene.ui.composable.transitions.lockscreenToGoneTran
import com.android.systemui.scene.ui.composable.transitions.lockscreenToQuickSettingsTransition
import com.android.systemui.scene.ui.composable.transitions.lockscreenToShadeTransition
import com.android.systemui.scene.ui.composable.transitions.lockscreenToSplitShadeTransition
-import com.android.systemui.scene.ui.composable.transitions.notificationsShadeToQuickSettingsShadeTransition
import com.android.systemui.scene.ui.composable.transitions.shadeToQuickSettingsTransition
import com.android.systemui.scene.ui.composable.transitions.toNotificationsShadeTransition
import com.android.systemui.scene.ui.composable.transitions.toQuickSettingsShadeTransition
@@ -172,13 +171,6 @@ val SceneContainerTransitions = transitions {
toQuickSettingsShadeTransition()
}
from(
- Overlays.NotificationsShade,
- to = Overlays.QuickSettingsShade,
- cuj = Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE,
- ) {
- notificationsShadeToQuickSettingsShadeTransition()
- }
- from(
Scenes.Gone,
to = Overlays.NotificationsShade,
key = SlightlyFasterShadeCollapse,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
index cb0d33cf5205..90c45eec9630 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
@@ -403,11 +403,14 @@ internal class SwipeAnimation<T : ContentKey>(
initialValue = initialOffset,
)
+ // The decay animation should only play if decayOffset exceeds targetOffset.
+ val lowerBound = checkNotNull(animatable.lowerBound) { "No lower bound" }
+ val upperBound = checkNotNull(animatable.upperBound) { "No upper bound" }
val willDecayReachBounds =
- when {
- targetOffset > initialOffset -> decayOffset >= targetOffset
- targetOffset < initialOffset -> decayOffset <= targetOffset
- else -> true
+ when (targetOffset) {
+ lowerBound -> decayOffset <= lowerBound
+ upperBound -> decayOffset >= upperBound
+ else -> error("Target $targetOffset should be $lowerBound or $upperBound")
}
if (willDecayReachBounds) {
@@ -421,6 +424,10 @@ internal class SwipeAnimation<T : ContentKey>(
appendLine(" targetOffset=$targetOffset")
appendLine(" initialVelocity=$initialVelocity")
appendLine(" decayOffset=$decayOffset")
+ appendLine(
+ " animateDecay result: reason=${result.endReason} " +
+ "value=${result.endState.value} velocity=${result.endState.velocity}"
+ )
}
}
return initialVelocity - result.endState.velocity
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 969003cb92f3..06e76d470a08 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -773,6 +773,36 @@ class DraggableHandlerTest {
}
@Test
+ fun startSwipeAnimationFromBound() = runGestureTest {
+ // Swipe down to go to SceneC.
+ mutableUserActionsA = mapOf(Swipe.Down to SceneC)
+
+ val dragController =
+ onDragStarted(
+ position = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f),
+ // Swipe up.
+ overSlop = up(0.5f),
+ // Should be ignored.
+ expectedConsumedOverSlop = 0f,
+ )
+
+ val transition = assertThat(transitionState).isSceneTransition()
+ assertThat(transition).hasFromScene(SceneA)
+ assertThat(transition).hasToScene(SceneC)
+ assertThat(transition).hasProgress(0f)
+
+ // Swipe down, but not enough to go to SceneC.
+ dragController.onDragStoppedAnimateNow(
+ velocity = velocityThreshold - 0.01f,
+ onAnimationStart = {
+ assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0f)
+ },
+ )
+
+ assertIdle(SceneA)
+ }
+
+ @Test
fun requireFullDistanceSwipe() = runGestureTest {
mutableUserActionsA +=
Swipe.Up to UserActionResult(SceneB, requiresFullDistanceSwipe = true)
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 36029177d4f6..6cc281ace481 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -23,6 +23,7 @@ import com.android.systemui.log.core.MessageBuffer
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockFontAxis
import com.android.systemui.plugins.clocks.ClockFontAxisSetting
+import com.android.systemui.plugins.clocks.ClockLogger
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.plugins.clocks.ClockPickerConfig
@@ -62,7 +63,7 @@ class DefaultClockProvider(
}
return if (isClockReactiveVariantsEnabled) {
- val buffers = messageBuffers ?: ClockMessageBuffers(LogUtil.DEFAULT_MESSAGE_BUFFER)
+ val buffers = messageBuffers ?: ClockMessageBuffers(ClockLogger.DEFAULT_MESSAGE_BUFFER)
val fontAxes = ClockFontAxis.merge(FlexClockController.FONT_AXES, settings.axes)
val clockSettings = settings.copy(axes = fontAxes.map { it.toSetting() })
val typefaceCache =
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/LogUtil.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/LogUtil.kt
deleted file mode 100644
index 34cb4ef7089d..000000000000
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/LogUtil.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.shared.clocks
-
-import com.android.systemui.log.core.LogLevel
-import com.android.systemui.log.core.LogcatOnlyMessageBuffer
-import com.android.systemui.log.core.Logger
-
-object LogUtil {
- // Used when MessageBuffers are not provided by the host application
- val DEFAULT_MESSAGE_BUFFER = LogcatOnlyMessageBuffer(LogLevel.INFO)
-
- // Only intended for use during initialization steps where the correct logger doesn't exist yet
- val FALLBACK_INIT_LOGGER = Logger(LogcatOnlyMessageBuffer(LogLevel.ERROR), "CLOCK_INIT")
-
- // Debug is primarially used for tests, but can also be used for tracking down hard issues.
- val DEBUG_MESSAGE_BUFFER = LogcatOnlyMessageBuffer(LogLevel.DEBUG)
-}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt
index 3eb519186a3e..55750b5e0925 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt
@@ -27,11 +27,10 @@ import android.widget.RelativeLayout
import androidx.annotation.VisibleForTesting
import com.android.app.animation.Interpolators
import com.android.systemui.customization.R
-import com.android.systemui.log.core.Logger
import com.android.systemui.plugins.clocks.ClockFontAxisSetting
+import com.android.systemui.plugins.clocks.ClockLogger
import com.android.systemui.shared.clocks.ClockContext
import com.android.systemui.shared.clocks.DigitTranslateAnimator
-import com.android.systemui.shared.clocks.LogUtil
import java.util.Locale
import kotlin.math.abs
import kotlin.math.max
@@ -40,8 +39,8 @@ import kotlin.math.min
fun clamp(value: Float, minVal: Float, maxVal: Float): Float = max(min(value, maxVal), minVal)
class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {
- protected val logger = Logger(clockCtx.messageBuffer, this::class.simpleName!!)
- get() = field ?: LogUtil.FALLBACK_INIT_LOGGER
+ protected val logger = ClockLogger(this, clockCtx.messageBuffer, this::class.simpleName!!)
+ get() = field ?: ClockLogger.INIT_LOGGER
@VisibleForTesting
var isAnimationEnabled = true
@@ -121,11 +120,7 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {
override fun addView(child: View?) {
if (child == null) return
- logger.d({ "addView($str1 @$int1)" }) {
- str1 = child::class.simpleName!!
- int1 = child.id
- }
-
+ logger.addView(child)
super.addView(child)
(child as? SimpleDigitalClockTextView)?.let {
it.digitTranslateAnimator = DigitTranslateAnimator(::invalidate)
@@ -135,58 +130,32 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {
}
fun refreshTime() {
- logger.d("refreshTime()")
+ logger.refreshTime()
digitalClockTextViewMap.forEach { (_, textView) -> textView.refreshText() }
}
override fun setVisibility(visibility: Int) {
- if (visibility != this.visibility) {
- logger.d({ "setVisibility(${str1 ?: int1})" }) {
- int1 = visibility
- str1 =
- when (visibility) {
- VISIBLE -> "VISIBLE"
- INVISIBLE -> "INVISIBLE"
- GONE -> "GONE"
- else -> null
- }
- }
- }
-
+ logger.setVisibility(visibility)
super.setVisibility(visibility)
}
- private var loggedAlpha = 1000f
-
override fun setAlpha(alpha: Float) {
- val delta = if (alpha <= 0f || alpha >= 1f) 0.001f else 0.5f
- if (abs(loggedAlpha - alpha) >= delta) {
- loggedAlpha = alpha
- logger.d({ "setAlpha($double1)" }) { double1 = alpha.toDouble() }
- }
+ logger.setAlpha(alpha)
super.setAlpha(alpha)
}
- private val isDrawn: Boolean
- get() = (mPrivateFlags and 0x20 /* PFLAG_DRAWN */) > 0
-
override fun invalidate() {
- if (isDrawn && visibility == VISIBLE) {
- logger.d("invalidate()")
- }
-
+ logger.invalidate()
super.invalidate()
}
override fun requestLayout() {
- if (!isLayoutRequested()) {
- logger.d("requestLayout()")
- }
+ logger.requestLayout()
super.requestLayout()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- logger.d("onMeasure()")
+ logger.onMeasure()
calculateSize(widthMeasureSpec, heightMeasureSpec)?.let { size ->
setMeasuredDimension(size.x, size.y)
} ?: run { super.onMeasure(widthMeasureSpec, heightMeasureSpec) }
@@ -198,12 +167,12 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
- logger.d("onLayout()")
+ logger.onLayout()
super.onLayout(changed, left, top, right, bottom)
}
override fun onDraw(canvas: Canvas) {
- logger.d("onDraw()")
+ logger.onDraw()
super.onDraw(canvas)
digitalClockTextViewMap.forEach { (id, textView) ->
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
index fbd5887c5b54..db39162205b2 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
@@ -37,15 +37,13 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.GSFAxes
import com.android.systemui.animation.TextAnimator
import com.android.systemui.customization.R
-import com.android.systemui.log.core.Logger
import com.android.systemui.plugins.clocks.ClockFontAxisSetting
+import com.android.systemui.plugins.clocks.ClockLogger
import com.android.systemui.shared.clocks.ClockContext
import com.android.systemui.shared.clocks.DigitTranslateAnimator
import com.android.systemui.shared.clocks.DimensionParser
import com.android.systemui.shared.clocks.FontTextStyle
-import com.android.systemui.shared.clocks.LogUtil
import java.lang.Thread
-import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
@@ -95,8 +93,8 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
private val prevTextBounds = Rect()
// targetTextBounds holds the state we are interpolating to
private val targetTextBounds = Rect()
- protected val logger = Logger(clockCtx.messageBuffer, this::class.simpleName!!)
- get() = field ?: LogUtil.FALLBACK_INIT_LOGGER
+ protected val logger = ClockLogger(this, clockCtx.messageBuffer, this::class.simpleName!!)
+ get() = field ?: ClockLogger.INIT_LOGGER
private var aodDozingInterpolator: Interpolator? = null
@@ -147,7 +145,7 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- logger.d("onMeasure()")
+ logger.onMeasure()
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val layout = this.layout
@@ -208,9 +206,7 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
}
override fun onDraw(canvas: Canvas) {
- logger.d({ "onDraw(${str1?.replace("\n", "\\n")})" }) {
- str1 = textAnimator.textInterpolator.shapedText
- }
+ logger.onDraw(textAnimator.textInterpolator.shapedText)
val translation = getLocalTranslation()
canvas.translate(translation.x.toFloat(), translation.y.toFloat())
@@ -227,47 +223,23 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
}
override fun setVisibility(visibility: Int) {
- if (visibility != this.visibility) {
- logger.d({ "setVisibility(${str1 ?: int1})" }) {
- int1 = visibility
- str1 =
- when (visibility) {
- VISIBLE -> "VISIBLE"
- INVISIBLE -> "INVISIBLE"
- GONE -> "GONE"
- else -> null
- }
- }
- }
-
+ logger.setVisibility(visibility)
super.setVisibility(visibility)
}
- private var loggedAlpha = 1000f
-
override fun setAlpha(alpha: Float) {
- val delta = if (alpha <= 0f || alpha >= 1f) 0.001f else 0.5f
- if (abs(loggedAlpha - alpha) >= delta) {
- loggedAlpha = alpha
- logger.d({ "setAlpha($double1)" }) { double1 = alpha.toDouble() }
- }
+ logger.setAlpha(alpha)
super.setAlpha(alpha)
}
- private val isDrawn: Boolean
- get() = (mPrivateFlags and 0x20 /* PFLAG_DRAWN */) > 0
-
override fun invalidate() {
- if (isDrawn && visibility == VISIBLE) {
- logger.d("invalidate()")
- }
-
+ logger.invalidate()
super.invalidate()
(parent as? FlexClockView)?.invalidate()
}
fun refreshTime() {
- logger.d("refreshTime()")
+ logger.refreshTime()
refreshText()
}
@@ -472,7 +444,7 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
maxSingleDigitWidth = 0
for (i in 0..9) {
- lockScreenPaint.getTextBounds(i.toString(), 0, 1, rectForCalculate)
+ lockScreenPaint.getTextBounds("$i", 0, 1, rectForCalculate)
maxSingleDigitHeight = max(maxSingleDigitHeight, rectForCalculate.height())
maxSingleDigitWidth = max(maxSingleDigitWidth, rectForCalculate.width())
}
diff --git a/packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSecureSettingsRepository.kt b/packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSecureSettingsRepository.kt
index 21d8d4648824..e11a6d049721 100644
--- a/packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSecureSettingsRepository.kt
+++ b/packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSecureSettingsRepository.kt
@@ -32,6 +32,11 @@ class FakeSecureSettingsRepository : SecureSettingsRepository {
return intSetting(name, if (defaultValue) 1 else 0).map { it != 0 }
}
+ fun setBool(name: String, value: Boolean) {
+ settings.value =
+ settings.value.toMutableMap().apply { this[name] = (if (value) 1 else 0).toString() }
+ }
+
override suspend fun setInt(name: String, value: Int) {
settings.value = settings.value.toMutableMap().apply { this[name] = value.toString() }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
index b087ecf1a488..6d75c4ca3a38 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
@@ -46,7 +46,7 @@ import androidx.test.filters.SmallTest;
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.util.settings.SecureSettings;
@@ -86,7 +86,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase {
@Mock
private IRemoteMagnificationAnimationCallback mAnimationCallback;
@Mock
- private OverviewProxyService mOverviewProxyService;
+ private LauncherProxyService mLauncherProxyService;
@Mock
private SecureSettings mSecureSettings;
@Mock
@@ -114,7 +114,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase {
assertNotNull(mTestableLooper);
mMagnification = new MagnificationImpl(getContext(),
mTestableLooper.getLooper(), mContext.getMainExecutor(), mCommandQueue,
- mModeSwitchesController, mSysUiState, mOverviewProxyService, mSecureSettings,
+ mModeSwitchesController, mSysUiState, mLauncherProxyService, mSecureSettings,
mDisplayTracker, getContext().getSystemService(DisplayManager.class),
mA11yLogger, mIWindowManager, mAccessibilityManager,
mViewCaptureAwareWindowManager);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt
index 4c329dcf2f2b..cebd05d92537 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt
@@ -18,20 +18,12 @@ package com.android.systemui.bluetooth.qsdialog
import android.bluetooth.BluetoothLeBroadcast
import android.bluetooth.BluetoothLeBroadcastMetadata
-import android.content.ContentResolver
-import android.content.applicationContext
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.settingslib.bluetooth.BluetoothEventManager
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast
-import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant
-import com.android.settingslib.bluetooth.LocalBluetoothProfileManager
-import com.android.settingslib.bluetooth.VolumeControlProfile
-import com.android.settingslib.volume.shared.AudioSharingLogger
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -46,14 +38,10 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.kotlin.any
-import org.mockito.kotlin.doReturn
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.spy
import org.mockito.kotlin.times
import org.mockito.kotlin.whenever
@@ -78,7 +66,7 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testIsAudioSharingOn_flagOff_false() =
+ fun isAudioSharingOn_flagOff_false() =
with(kosmos) {
testScope.runTest {
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(false)
@@ -90,7 +78,7 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testIsAudioSharingOn_flagOn_notInAudioSharing_false() =
+ fun isAudioSharingOn_flagOn_notInAudioSharing_false() =
with(kosmos) {
testScope.runTest {
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
@@ -103,7 +91,7 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testIsAudioSharingOn_flagOn_inAudioSharing_true() =
+ fun isAudioSharingOn_flagOn_inAudioSharing_true() =
with(kosmos) {
testScope.runTest {
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
@@ -116,7 +104,7 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testAudioSourceStateUpdate_notInAudioSharing_returnEmpty() =
+ fun audioSourceStateUpdate_notInAudioSharing_returnEmpty() =
with(kosmos) {
testScope.runTest {
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
@@ -129,7 +117,7 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testAudioSourceStateUpdate_inAudioSharing_returnUnit() =
+ fun audioSourceStateUpdate_inAudioSharing_returnUnit() =
with(kosmos) {
testScope.runTest {
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
@@ -144,7 +132,7 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testHandleAudioSourceWhenReady_flagOff_sourceNotAdded() =
+ fun handleAudioSourceWhenReady_flagOff_sourceNotAdded() =
with(kosmos) {
testScope.runTest {
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(false)
@@ -157,7 +145,7 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testHandleAudioSourceWhenReady_noProfile_sourceNotAdded() =
+ fun handleAudioSourceWhenReady_noProfile_sourceNotAdded() =
with(kosmos) {
testScope.runTest {
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
@@ -171,36 +159,41 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testHandleAudioSourceWhenReady_hasProfileButAudioSharingOff_sourceNotAdded() =
+ fun handleAudioSourceWhenReady_hasProfileButAudioSharingNeverTriggered_sourceNotAdded() =
with(kosmos) {
testScope.runTest {
- bluetoothTileDialogAudioSharingRepository.setInAudioSharing(true)
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile(
localBluetoothLeBroadcast
)
val job = launch { underTest.handleAudioSourceWhenReady() }
runCurrent()
- bluetoothTileDialogAudioSharingRepository.setInAudioSharing(false)
- runCurrent()
+ // Verify callback registered for onBroadcastStartedOrStopped
+ verify(localBluetoothLeBroadcast).registerServiceCallBack(any(), any())
assertThat(bluetoothTileDialogAudioSharingRepository.sourceAdded).isFalse()
job.cancel()
}
}
@Test
- fun testHandleAudioSourceWhenReady_audioSharingOnButNoPlayback_sourceNotAdded() =
+ fun handleAudioSourceWhenReady_audioSharingTriggeredButFailed_sourceNotAdded() =
with(kosmos) {
testScope.runTest {
- bluetoothTileDialogAudioSharingRepository.setInAudioSharing(false)
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile(
localBluetoothLeBroadcast
)
val job = launch { underTest.handleAudioSourceWhenReady() }
runCurrent()
- bluetoothTileDialogAudioSharingRepository.setInAudioSharing(true)
+ // Verify callback registered for onBroadcastStartedOrStopped
+ verify(localBluetoothLeBroadcast)
+ .registerServiceCallBack(any(), callbackCaptor.capture())
+ // Audio sharing started failed, trigger onBroadcastStartFailed
+ whenever(localBluetoothLeBroadcast.isEnabled(null)).thenReturn(false)
+ underTest.startAudioSharing()
+ runCurrent()
+ callbackCaptor.value.onBroadcastStartFailed(0)
runCurrent()
assertThat(bluetoothTileDialogAudioSharingRepository.sourceAdded).isFalse()
@@ -209,122 +202,59 @@ class AudioSharingInteractorTest : SysuiTestCase() {
}
@Test
- fun testHandleAudioSourceWhenReady_audioSharingOnAndPlaybackStarts_sourceAdded() =
+ fun handleAudioSourceWhenReady_audioSharingTriggeredButMetadataNotReady_sourceNotAdded() =
with(kosmos) {
testScope.runTest {
- bluetoothTileDialogAudioSharingRepository.setInAudioSharing(false)
bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile(
localBluetoothLeBroadcast
)
val job = launch { underTest.handleAudioSourceWhenReady() }
runCurrent()
- bluetoothTileDialogAudioSharingRepository.setInAudioSharing(true)
- runCurrent()
+ // Verify callback registered for onBroadcastStartedOrStopped
verify(localBluetoothLeBroadcast)
.registerServiceCallBack(any(), callbackCaptor.capture())
runCurrent()
- callbackCaptor.value.onBroadcastMetadataChanged(0, bluetoothLeBroadcastMetadata)
+ underTest.startAudioSharing()
runCurrent()
+ // Verify callback registered for onBroadcastMetadataChanged
+ verify(localBluetoothLeBroadcast, times(2))
+ .registerServiceCallBack(any(), callbackCaptor.capture())
- assertThat(bluetoothTileDialogAudioSharingRepository.sourceAdded).isTrue()
- job.cancel()
- }
- }
-
- @Test
- fun testHandleAudioSourceWhenReady_skipInitialValue_noAudioSharing_sourceNotAdded() =
- with(kosmos) {
- testScope.runTest {
- val (broadcast, repository) = setupRepositoryImpl()
- val interactor =
- object :
- AudioSharingInteractorImpl(
- applicationContext,
- localBluetoothManager,
- repository,
- testDispatcher,
- ) {
- override suspend fun audioSharingAvailable() = true
- }
- val job = launch { interactor.handleAudioSourceWhenReady() }
- runCurrent()
- // Verify callback registered for onBroadcastStartedOrStopped
- verify(broadcast).registerServiceCallBack(any(), callbackCaptor.capture())
- runCurrent()
- // Verify source is not added
- verify(repository, never()).addSource()
+ assertThat(bluetoothTileDialogAudioSharingRepository.sourceAdded).isFalse()
job.cancel()
}
}
@Test
- fun testHandleAudioSourceWhenReady_skipInitialValue_newAudioSharing_sourceAdded() =
+ fun handleAudioSourceWhenReady_audioSharingTriggeredAndMetadataReady_sourceAdded() =
with(kosmos) {
testScope.runTest {
- val (broadcast, repository) = setupRepositoryImpl()
- val interactor =
- object :
- AudioSharingInteractorImpl(
- applicationContext,
- localBluetoothManager,
- repository,
- testDispatcher,
- ) {
- override suspend fun audioSharingAvailable() = true
- }
- val job = launch { interactor.handleAudioSourceWhenReady() }
+ bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true)
+ bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile(
+ localBluetoothLeBroadcast
+ )
+ val job = launch { underTest.handleAudioSourceWhenReady() }
runCurrent()
// Verify callback registered for onBroadcastStartedOrStopped
- verify(broadcast).registerServiceCallBack(any(), callbackCaptor.capture())
+ verify(localBluetoothLeBroadcast)
+ .registerServiceCallBack(any(), callbackCaptor.capture())
// Audio sharing started, trigger onBroadcastStarted
- whenever(broadcast.isEnabled(null)).thenReturn(true)
+ whenever(localBluetoothLeBroadcast.isEnabled(null)).thenReturn(true)
+ underTest.startAudioSharing()
+ runCurrent()
callbackCaptor.value.onBroadcastStarted(0, 0)
runCurrent()
// Verify callback registered for onBroadcastMetadataChanged
- verify(broadcast, times(2)).registerServiceCallBack(any(), callbackCaptor.capture())
+ verify(localBluetoothLeBroadcast, times(2))
+ .registerServiceCallBack(any(), callbackCaptor.capture())
runCurrent()
// Trigger onBroadcastMetadataChanged (ready to add source)
callbackCaptor.value.onBroadcastMetadataChanged(0, bluetoothLeBroadcastMetadata)
runCurrent()
- // Verify source added
- verify(repository).addSource()
+
+ assertThat(bluetoothTileDialogAudioSharingRepository.sourceAdded).isTrue()
job.cancel()
}
}
-
- private fun setupRepositoryImpl(): Pair<LocalBluetoothLeBroadcast, AudioSharingRepositoryImpl> {
- with(kosmos) {
- val broadcast =
- mock<LocalBluetoothLeBroadcast> {
- on { isProfileReady } doReturn true
- on { isEnabled(null) } doReturn false
- }
- val assistant =
- mock<LocalBluetoothLeBroadcastAssistant> { on { isProfileReady } doReturn true }
- val volumeControl = mock<VolumeControlProfile> { on { isProfileReady } doReturn true }
- val profileManager =
- mock<LocalBluetoothProfileManager> {
- on { leAudioBroadcastProfile } doReturn broadcast
- on { leAudioBroadcastAssistantProfile } doReturn assistant
- on { volumeControlProfile } doReturn volumeControl
- }
- whenever(localBluetoothManager.profileManager).thenReturn(profileManager)
- whenever(localBluetoothManager.eventManager).thenReturn(mock<BluetoothEventManager> {})
-
- val repository =
- AudioSharingRepositoryImpl(
- localBluetoothManager,
- com.android.settingslib.volume.data.repository.AudioSharingRepositoryImpl(
- mock<ContentResolver> {},
- localBluetoothManager,
- testScope.backgroundScope,
- testScope.testScheduler,
- mock<AudioSharingLogger> {},
- ),
- testDispatcher,
- )
- return Pair(broadcast, spy(repository))
- }
- }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
index 038ea9ccaaa9..809099e0d464 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
@@ -30,6 +30,7 @@ import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.broadcastDispatcher
@@ -279,6 +280,7 @@ class CommunalSettingsRepositoryImplTest(flags: FlagsParameterization?) : SysuiT
}
@Test
+ @DisableFlags(FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND)
fun backgroundType_defaultValue() =
testScope.runTest {
val backgroundType by collectLastValue(underTest.getBackground(PRIMARY_USER))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
index 26859b6e10f8..5510710b9b3f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
@@ -18,8 +18,6 @@
package com.android.systemui.communal.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.Swipe
@@ -42,9 +40,9 @@ import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.shade.shared.flag.DualShade
-import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
@@ -72,33 +70,21 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun actions_singleShade() =
testScope.runTest {
val actions by collectLastValue(underTest.actions)
+ kosmos.enableSingleShade()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = true,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
@@ -106,34 +92,22 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun actions_splitShade() =
testScope.runTest {
val actions by collectLastValue(underTest.actions)
+ kosmos.enableSplitShade()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
.isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = true,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
@@ -142,30 +116,22 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun actions_dualShade() =
testScope.runTest {
val actions by collectLastValue(underTest.actions)
+ kosmos.enableDualShade()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Dual,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
.isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Dual,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(isShadeTouchable = true, isDeviceUnlocked = true, shadeMode = ShadeMode.Dual)
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
@@ -173,11 +139,7 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
.isEqualTo(UserActionResult.ShowOverlay(Overlays.NotificationsShade))
}
- private fun TestScope.setUpState(
- isShadeTouchable: Boolean,
- isDeviceUnlocked: Boolean,
- shadeMode: ShadeMode,
- ) {
+ private fun TestScope.setUpState(isShadeTouchable: Boolean, isDeviceUnlocked: Boolean) {
if (isShadeTouchable) {
kosmos.powerInteractor.setAwakeForTest()
} else {
@@ -189,10 +151,6 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() {
} else {
lockDevice()
}
-
- if (shadeMode !is ShadeMode.Dual) {
- kosmos.fakeShadeRepository.setShadeLayoutWide(shadeMode is ShadeMode.Split)
- }
runCurrent()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt
index e19ea365fa1f..e5670627735c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt
@@ -18,8 +18,6 @@
package com.android.systemui.dreams.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.Swipe
@@ -42,9 +40,9 @@ import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.shade.shared.flag.DualShade
-import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
@@ -72,36 +70,24 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun actions_communalNotAvailable_singleShade() =
testScope.runTest {
+ kosmos.enableSingleShade()
kosmos.setCommunalAvailable(false)
val actions by collectLastValue(underTest.actions)
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = true,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
@@ -110,18 +96,14 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun actions_communalNotAvailable_splitShade() =
testScope.runTest {
+ kosmos.enableSplitShade()
kosmos.setCommunalAvailable(false)
val actions by collectLastValue(underTest.actions)
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
@@ -129,18 +111,10 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = true,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
@@ -150,18 +124,14 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun actions_communalNotAvailable_dualShade() =
testScope.runTest {
+ kosmos.enableDualShade()
kosmos.setCommunalAvailable(false)
val actions by collectLastValue(underTest.actions)
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Dual,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
@@ -169,14 +139,10 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
assertThat(actions?.get(Swipe.Start)).isNull()
assertThat(actions?.get(Swipe.End)).isNull()
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Dual,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(isShadeTouchable = true, isDeviceUnlocked = true, shadeMode = ShadeMode.Dual)
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
@@ -186,36 +152,24 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun actions_communalAvailable_singleShade() =
testScope.runTest {
+ kosmos.enableSingleShade()
kosmos.setCommunalAvailable(true)
val actions by collectLastValue(underTest.actions)
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = true,
- shadeMode = ShadeMode.Single,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
@@ -224,18 +178,14 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun actions_communalAvailable_splitShade() =
testScope.runTest {
+ kosmos.enableSplitShade()
kosmos.setCommunalAvailable(true)
val actions by collectLastValue(underTest.actions)
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
@@ -243,18 +193,10 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = true,
- shadeMode = ShadeMode.Split,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
@@ -264,18 +206,14 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun actions_communalAvailable_dualShade() =
testScope.runTest {
+ kosmos.enableDualShade()
kosmos.setCommunalAvailable(true)
val actions by collectLastValue(underTest.actions)
- setUpState(
- isShadeTouchable = true,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Dual,
- )
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = false)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
assertThat(actions?.get(Swipe.Down))
@@ -283,14 +221,10 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal))
assertThat(actions?.get(Swipe.End)).isNull()
- setUpState(
- isShadeTouchable = false,
- isDeviceUnlocked = false,
- shadeMode = ShadeMode.Dual,
- )
+ setUpState(isShadeTouchable = false, isDeviceUnlocked = false)
assertThat(actions).isEmpty()
- setUpState(isShadeTouchable = true, isDeviceUnlocked = true, shadeMode = ShadeMode.Dual)
+ setUpState(isShadeTouchable = true, isDeviceUnlocked = true)
assertThat(actions).isNotEmpty()
assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
assertThat(actions?.get(Swipe.Down))
@@ -299,11 +233,7 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
assertThat(actions?.get(Swipe.End)).isNull()
}
- private fun TestScope.setUpState(
- isShadeTouchable: Boolean,
- isDeviceUnlocked: Boolean,
- shadeMode: ShadeMode,
- ) {
+ private fun TestScope.setUpState(isShadeTouchable: Boolean, isDeviceUnlocked: Boolean) {
if (isShadeTouchable) {
kosmos.powerInteractor.setAwakeForTest()
} else {
@@ -315,10 +245,6 @@ class DreamUserActionsViewModelTest : SysuiTestCase() {
} else {
lockDevice()
}
-
- if (shadeMode !is ShadeMode.Dual) {
- kosmos.fakeShadeRepository.setShadeLayoutWide(shadeMode is ShadeMode.Split)
- }
runCurrent()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt
index 5e023a203267..6899d23bcfd7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt
@@ -34,7 +34,7 @@ import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
import com.android.systemui.inputdevice.tutorial.tutorialSchedulerRepository
import com.android.systemui.keyboard.data.repository.keyboardRepository
import com.android.systemui.kosmos.testScope
-import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
+import com.android.systemui.recents.LauncherProxyService.LauncherProxyListener
import com.android.systemui.testKosmos
import com.android.systemui.touchpad.data.repository.touchpadRepository
import com.android.systemui.user.data.repository.fakeUserRepository
@@ -68,7 +68,7 @@ class KeyboardTouchpadEduInteractorParameterizedTest(private val gestureType: Ge
private val keyboardRepository = kosmos.keyboardRepository
private val tutorialSchedulerRepository = kosmos.tutorialSchedulerRepository
private val userRepository = kosmos.fakeUserRepository
- private val overviewProxyService = kosmos.mockOverviewProxyService
+ private val launcherProxyService = kosmos.mockLauncherProxyService
private val underTest: KeyboardTouchpadEduInteractor = kosmos.keyboardTouchpadEduInteractor
private val eduClock = kosmos.fakeEduClock
@@ -519,8 +519,8 @@ class KeyboardTouchpadEduInteractorParameterizedTest(private val gestureType: Ge
}
private fun updateContextualEduStats(isTrackpadGesture: Boolean, gestureType: GestureType) {
- val listenerCaptor = argumentCaptor<OverviewProxyListener>()
- verify(overviewProxyService).addCallback(listenerCaptor.capture())
+ val listenerCaptor = argumentCaptor<LauncherProxyListener>()
+ verify(launcherProxyService).addCallback(listenerCaptor.capture())
listenerCaptor.firstValue.updateContextualEduStats(isTrackpadGesture, gestureType)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
index 692b9c67f322..dc393c01dce1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
@@ -32,7 +32,7 @@ import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
import com.android.systemui.inputdevice.tutorial.tutorialSchedulerRepository
import com.android.systemui.keyboard.data.repository.keyboardRepository
import com.android.systemui.kosmos.testScope
-import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
+import com.android.systemui.recents.LauncherProxyService.LauncherProxyListener
import com.android.systemui.testKosmos
import com.android.systemui.touchpad.data.repository.touchpadRepository
import com.google.common.truth.Truth.assertThat
@@ -58,7 +58,7 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() {
private val touchpadRepository = kosmos.touchpadRepository
private val keyboardRepository = kosmos.keyboardRepository
private val tutorialSchedulerRepository = kosmos.tutorialSchedulerRepository
- private val overviewProxyService = kosmos.mockOverviewProxyService
+ private val launcherProxyService = kosmos.mockLauncherProxyService
private val underTest: KeyboardTouchpadEduInteractor = kosmos.keyboardTouchpadEduInteractor
private val eduClock = kosmos.fakeEduClock
@@ -167,16 +167,16 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() {
keyboardRepository.setIsAnyKeyboardConnected(true)
}
- private fun getOverviewProxyListener(): OverviewProxyListener {
- val listenerCaptor = argumentCaptor<OverviewProxyListener>()
- verify(overviewProxyService).addCallback(listenerCaptor.capture())
+ private fun getLauncherProxyListener(): LauncherProxyListener {
+ val listenerCaptor = argumentCaptor<LauncherProxyListener>()
+ verify(launcherProxyService).addCallback(listenerCaptor.capture())
return listenerCaptor.firstValue
}
private fun TestScope.triggerEducation(gestureType: GestureType) {
// Increment max number of signal to try triggering education
for (i in 1..KeyboardTouchpadEduInteractor.MAX_SIGNAL_COUNT) {
- val listener = getOverviewProxyListener()
+ val listener = getLauncherProxyListener()
listener.updateContextualEduStats(/* isTrackpadGesture= */ false, gestureType)
}
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt
index 698fac107a1d..4d81cb0ce726 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.keyboard.shortcut.data.repository
import android.content.Context
import android.content.Context.INPUT_SERVICE
import android.content.Intent
+import android.hardware.input.FakeInputManager
import android.hardware.input.InputGestureData
import android.hardware.input.InputManager
import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
@@ -57,13 +58,14 @@ class CustomInputGesturesRepositoryTest : SysuiTestCase() {
private val secondaryUserContext: Context = mock()
private var activeUserContext: Context = primaryUserContext
- private val kosmos = testKosmos().also {
- it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { activeUserContext })
- }
+ private val kosmos =
+ testKosmos().also {
+ it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { activeUserContext })
+ }
private val inputManager = kosmos.fakeInputManager.inputManager
private val broadcastDispatcher = kosmos.broadcastDispatcher
- private val inputManagerForSecondaryUser: InputManager = mock()
+ private val inputManagerForSecondaryUser: InputManager = FakeInputManager().inputManager
private val testScope = kosmos.testScope
private val testHelper = kosmos.shortcutHelperTestHelper
private val customInputGesturesRepository = kosmos.customInputGesturesRepository
@@ -94,9 +96,10 @@ class CustomInputGesturesRepositoryTest : SysuiTestCase() {
fun customInputGestures_initialValueReturnsDataFromAPI() {
testScope.runTest {
val customInputGestures = listOf(allAppsInputGestureData)
- whenever(
- inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
- ).then { return@then customInputGestures }
+ whenever(inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY))
+ .then {
+ return@then customInputGestures
+ }
val inputGestures by collectLastValue(customInputGesturesRepository.customInputGestures)
@@ -108,9 +111,10 @@ class CustomInputGesturesRepositoryTest : SysuiTestCase() {
fun customInputGestures_isUpdatedToMostRecentDataAfterNewGestureIsAdded() {
testScope.runTest {
var customInputGestures = listOf<InputGestureData>()
- whenever(
- inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
- ).then { return@then customInputGestures }
+ whenever(inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY))
+ .then {
+ return@then customInputGestures
+ }
whenever(inputManager.addCustomInputGesture(any())).then { invocation ->
val inputGesture = invocation.getArgument<InputGestureData>(0)
customInputGestures = customInputGestures + inputGesture
@@ -129,10 +133,10 @@ class CustomInputGesturesRepositoryTest : SysuiTestCase() {
fun retrieveCustomInputGestures_retrievesMostRecentData() {
testScope.runTest {
var customInputGestures = listOf<InputGestureData>()
- whenever(
- inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
- ).then { return@then customInputGestures }
-
+ whenever(inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY))
+ .then {
+ return@then customInputGestures
+ }
assertThat(customInputGesturesRepository.retrieveCustomInputGestures()).isEmpty()
@@ -143,24 +147,38 @@ class CustomInputGesturesRepositoryTest : SysuiTestCase() {
}
}
+ @Test
+ fun getInputGestureByTrigger_returnsInputGestureFromInputManager() =
+ testScope.runTest {
+ inputManager.addCustomInputGesture(allAppsInputGestureData)
+
+ val inputGestureData =
+ customInputGesturesRepository.getInputGestureByTrigger(
+ allAppsInputGestureData.trigger
+ )
+
+ assertThat(inputGestureData).isEqualTo(allAppsInputGestureData)
+ }
+
private fun setCustomInputGesturesForPrimaryUser(vararg inputGesture: InputGestureData) {
- whenever(
- inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
- ).thenReturn(inputGesture.toList())
+ whenever(inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY))
+ .thenReturn(inputGesture.toList())
}
private fun setCustomInputGesturesForSecondaryUser(vararg inputGesture: InputGestureData) {
whenever(
- inputManagerForSecondaryUser.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
- ).thenReturn(inputGesture.toList())
+ inputManagerForSecondaryUser.getCustomInputGestures(
+ /* filter= */ InputGestureData.Filter.KEY
+ )
+ )
+ .thenReturn(inputGesture.toList())
}
private fun switchToSecondaryUser() {
activeUserContext = secondaryUserContext
broadcastDispatcher.sendIntentToMatchingReceiversOnly(
context,
- Intent(Intent.ACTION_USER_SWITCHED)
+ Intent(Intent.ACTION_USER_SWITCHED),
)
}
-
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt
index 4cfb26e6555b..522572dcffb7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt
@@ -24,6 +24,7 @@ import android.hardware.input.InputGestureData
import android.hardware.input.InputGestureData.createKeyTrigger
import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_DOES_NOT_EXIST
import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_HOME
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION
import android.hardware.input.fakeInputManager
import android.platform.test.annotations.DisableFlags
@@ -336,28 +337,6 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() {
}
}
- private suspend fun customizeShortcut(
- customizationRequest: ShortcutCustomizationRequestInfo,
- keyCombination: KeyCombination? = null,
- ): ShortcutCustomizationRequestResult {
- repo.onCustomizationRequested(customizationRequest)
- repo.updateUserKeyCombination(keyCombination)
-
- return when (customizationRequest) {
- is SingleShortcutCustomization.Add -> {
- repo.confirmAndSetShortcutCurrentlyBeingCustomized()
- }
-
- is SingleShortcutCustomization.Delete -> {
- repo.deleteShortcutCurrentlyBeingCustomized()
- }
-
- else -> {
- ShortcutCustomizationRequestResult.ERROR_OTHER
- }
- }
- }
-
@Test
@EnableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
fun categories_isUpdatedAfterCustomShortcutsAreReset() {
@@ -387,10 +366,66 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() {
}
}
+ @Test
+ fun selectedKeyCombinationIsAvailable_whenTriggerIsNotRegisteredInInputManager() =
+ testScope.runTest {
+ helper.toggle(deviceId = 123)
+ repo.onCustomizationRequested(allAppsShortcutAddRequest)
+ repo.updateUserKeyCombination(standardKeyCombination)
+
+ assertThat(repo.isSelectedKeyCombinationAvailable()).isTrue()
+ }
+
+ @Test
+ fun selectedKeyCombinationIsNotAvailable_whenTriggerIsRegisteredInInputManager() =
+ testScope.runTest {
+ inputManager.addCustomInputGesture(buildInputGestureWithStandardKeyCombination())
+
+ helper.toggle(deviceId = 123)
+ repo.onCustomizationRequested(allAppsShortcutAddRequest)
+ repo.updateUserKeyCombination(standardKeyCombination)
+
+ assertThat(repo.isSelectedKeyCombinationAvailable()).isFalse()
+ }
+
private fun setApiAppLaunchBookmarks(appLaunchBookmarks: List<InputGestureData>) {
whenever(inputManager.appLaunchBookmarks).thenReturn(appLaunchBookmarks)
}
+ private suspend fun customizeShortcut(
+ customizationRequest: ShortcutCustomizationRequestInfo,
+ keyCombination: KeyCombination? = null,
+ ): ShortcutCustomizationRequestResult {
+ repo.onCustomizationRequested(customizationRequest)
+ repo.updateUserKeyCombination(keyCombination)
+
+ return when (customizationRequest) {
+ is SingleShortcutCustomization.Add -> {
+ repo.confirmAndSetShortcutCurrentlyBeingCustomized()
+ }
+
+ is SingleShortcutCustomization.Delete -> {
+ repo.deleteShortcutCurrentlyBeingCustomized()
+ }
+
+ else -> {
+ ShortcutCustomizationRequestResult.ERROR_OTHER
+ }
+ }
+ }
+
+ private fun buildInputGestureWithStandardKeyCombination() =
+ InputGestureData.Builder()
+ .setKeyGestureType(KEY_GESTURE_TYPE_HOME)
+ .setTrigger(
+ createKeyTrigger(
+ /* keycode= */ standardKeyCombination.keyCode!!,
+ /* modifierState= */ standardKeyCombination.modifiers and
+ ALL_SUPPORTED_MODIFIERS,
+ )
+ )
+ .build()
+
private fun simpleInputGestureDataForAppLaunchShortcut(
keyCode: Int = KEYCODE_A,
modifiers: Int = META_CTRL_ON or META_ALT_ON,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt
index d9d34f5ace7b..6eef5eb09812 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt
@@ -18,11 +18,15 @@ package com.android.systemui.keyboard.shortcut.ui.viewmodel
import android.content.Context
import android.content.Context.INPUT_SERVICE
-import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_ALREADY_EXISTS
+import android.hardware.input.InputGestureData
+import android.hardware.input.InputGestureData.createKeyTrigger
import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_OTHER
import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_RESERVED_GESTURE
-import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_HOME
import android.hardware.input.fakeInputManager
+import android.view.KeyEvent.KEYCODE_A
+import android.view.KeyEvent.META_CTRL_ON
+import android.view.KeyEvent.META_META_ON
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -30,7 +34,6 @@ import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allAppsInputGestureData
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allAppsShortcutAddRequest
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allAppsShortcutDeleteRequest
-import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.goHomeInputGestureData
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.keyDownEventWithActionKeyPressed
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.keyDownEventWithoutActionKeyPressed
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.keyUpEventWithActionKeyPressed
@@ -44,16 +47,17 @@ import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiSt
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState.DeleteShortcutDialog
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState.ResetShortcutDialog
import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.res.R
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.userTracker
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
@@ -63,7 +67,7 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
private val mockUserContext: Context = mock()
private val kosmos =
- testKosmos().also {
+ testKosmos().useUnconfinedTestDispatcher().also {
it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { mockUserContext })
}
private val testScope = kosmos.testScope
@@ -75,6 +79,7 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
fun setup() {
helper.showFromActivity()
whenever(mockUserContext.getSystemService(INPUT_SERVICE)).thenReturn(inputManager)
+ testScope.backgroundScope.launch { viewModel.activate() }
}
@Test
@@ -146,8 +151,6 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
fun uiState_becomeInactiveAfterSuccessfullySettingShortcut() {
testScope.runTest {
val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
- whenever(inputManager.addCustomInputGesture(any()))
- .thenReturn(CUSTOM_INPUT_GESTURE_RESULT_SUCCESS)
openAddShortcutDialogAndSetShortcut()
@@ -166,11 +169,38 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
}
@Test
- fun uiState_errorMessage_isKeyCombinationInUse_whenKeyCombinationAlreadyExists() {
+ fun uiState_errorMessage_onKeyPressed_isKeyCombinationInUse_whenKeyCombinationAlreadyExists() {
testScope.runTest {
+ inputManager.addCustomInputGesture(buildSimpleInputGestureWithMetaCtrlATrigger())
+ val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
+
+ openAddShortcutDialogAndPressKeyCombination()
+
+ assertThat((uiState as AddShortcutDialog).errorMessage)
+ .isEqualTo(
+ context.getString(
+ R.string.shortcut_customizer_key_combination_in_use_error_message
+ )
+ )
+ }
+ }
+
+ @Test
+ fun uiState_errorMessage_onKeyPressed_isEmpty_whenKeyCombinationIsAvailable() {
+ testScope.runTest {
+ val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
+
+ openAddShortcutDialogAndPressKeyCombination()
+
+ assertThat((uiState as AddShortcutDialog).errorMessage).isEmpty()
+ }
+ }
+
+ @Test
+ fun uiState_errorMessage_onSetShortcut_isKeyCombinationInUse_whenKeyCombinationAlreadyExists() {
+ testScope.runTest {
+ inputManager.addCustomInputGesture(buildSimpleInputGestureWithMetaCtrlATrigger())
val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
- whenever(inputManager.addCustomInputGesture(any()))
- .thenReturn(CUSTOM_INPUT_GESTURE_RESULT_ERROR_ALREADY_EXISTS)
openAddShortcutDialogAndSetShortcut()
@@ -184,11 +214,12 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
}
@Test
- fun uiState_errorMessage_isKeyCombinationInUse_whenKeyCombinationIsReserved() {
+ fun uiState_errorMessage_onSetShortcut_isKeyCombinationInUse_whenKeyCombinationIsReserved() {
testScope.runTest {
+ inputManager.addCustomInputGesture(buildSimpleInputGestureWithMetaCtrlATrigger())
+ kosmos.fakeInputManager.addCustomInputGestureErrorCode =
+ CUSTOM_INPUT_GESTURE_RESULT_ERROR_RESERVED_GESTURE
val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
- whenever(inputManager.addCustomInputGesture(any()))
- .thenReturn(CUSTOM_INPUT_GESTURE_RESULT_ERROR_RESERVED_GESTURE)
openAddShortcutDialogAndSetShortcut()
@@ -202,11 +233,12 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
}
@Test
- fun uiState_errorMessage_isGenericError_whenErrorIsUnknown() {
+ fun uiState_errorMessage_onSetShortcut_isGenericError_whenErrorIsUnknown() {
testScope.runTest {
+ inputManager.addCustomInputGesture(buildSimpleInputGestureWithMetaCtrlATrigger())
+ kosmos.fakeInputManager.addCustomInputGestureErrorCode =
+ CUSTOM_INPUT_GESTURE_RESULT_ERROR_OTHER
val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
- whenever(inputManager.addCustomInputGesture(any()))
- .thenReturn(CUSTOM_INPUT_GESTURE_RESULT_ERROR_OTHER)
openAddShortcutDialogAndSetShortcut()
@@ -219,10 +251,7 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
fun uiState_becomesInactiveAfterSuccessfullyDeletingShortcut() {
testScope.runTest {
val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
- whenever(inputManager.getCustomInputGestures(any()))
- .thenReturn(listOf(goHomeInputGestureData, allAppsInputGestureData))
- whenever(inputManager.removeCustomInputGesture(any()))
- .thenReturn(CUSTOM_INPUT_GESTURE_RESULT_SUCCESS)
+ inputManager.addCustomInputGesture(allAppsInputGestureData)
openDeleteShortcutDialogAndDeleteShortcut()
@@ -234,7 +263,6 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
fun uiState_becomesInactiveAfterSuccessfullyResettingShortcuts() {
testScope.runTest {
val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
- whenever(inputManager.getCustomInputGestures(any())).thenReturn(emptyList())
openResetShortcutDialogAndResetAllCustomShortcuts()
@@ -297,24 +325,42 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
}
}
+ @Test
+ fun uiState_pressedKeys_resetsToEmpty_onClearSelectedShortcutKeyCombination() {
+ testScope.runTest {
+ val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
+ viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
+ viewModel.onShortcutKeyCombinationSelected(keyDownEventWithActionKeyPressed)
+ viewModel.onShortcutKeyCombinationSelected(keyUpEventWithActionKeyPressed)
+ viewModel.clearSelectedKeyCombination()
+ assertThat((uiState as AddShortcutDialog).pressedKeys).isEmpty()
+ }
+ }
+
private suspend fun openAddShortcutDialogAndSetShortcut() {
- viewModel.onShortcutCustomizationRequested(allAppsShortcutAddRequest)
+ openAddShortcutDialogAndPressKeyCombination()
+ viewModel.onSetShortcut()
+ }
+ private fun openAddShortcutDialogAndPressKeyCombination() {
+ viewModel.onShortcutCustomizationRequested(allAppsShortcutAddRequest)
viewModel.onShortcutKeyCombinationSelected(keyDownEventWithActionKeyPressed)
viewModel.onShortcutKeyCombinationSelected(keyUpEventWithActionKeyPressed)
-
- viewModel.onSetShortcut()
}
private suspend fun openDeleteShortcutDialogAndDeleteShortcut() {
viewModel.onShortcutCustomizationRequested(allAppsShortcutDeleteRequest)
-
viewModel.deleteShortcutCurrentlyBeingCustomized()
}
private suspend fun openResetShortcutDialogAndResetAllCustomShortcuts() {
viewModel.onShortcutCustomizationRequested(ShortcutCustomizationRequestInfo.Reset)
-
viewModel.resetAllCustomShortcuts()
}
+
+ private fun buildSimpleInputGestureWithMetaCtrlATrigger() =
+ InputGestureData.Builder()
+ .setKeyGestureType(KEY_GESTURE_TYPE_HOME)
+ .setTrigger(createKeyTrigger(KEYCODE_A, META_CTRL_ON or META_META_ON))
+ .build()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
index 930096463354..3f2e78cdfb52 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
@@ -39,6 +39,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -85,11 +87,13 @@ class FromAodTransitionInteractorTest : SysuiTestCase() {
private lateinit var powerInteractor: PowerInteractor
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
+ private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
@Before
fun setup() {
powerInteractor = kosmos.powerInteractor
transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy
+ bouncerRepository = kosmos.fakeKeyguardBouncerRepository
underTest = kosmos.fromAodTransitionInteractor
underTest.start()
@@ -304,6 +308,29 @@ class FromAodTransitionInteractorTest : SysuiTestCase() {
}
@Test
+ fun testWakeAndUnlock_transitionsToGone_evenIfBouncerShows() =
+ testScope.runTest {
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK
+ )
+ runCurrent()
+ bouncerRepository.setPrimaryShow(true)
+ runCurrent()
+ powerInteractor.setAwakeForTest()
+ runCurrent()
+
+ // Waking up from wake and unlock should not start any transitions, we'll wait for the
+ // dismiss call.
+ assertThat(transitionRepository).noTransitionsStarted()
+
+ underTest.dismissAod()
+ advanceTimeBy(100) // account for debouncing
+
+ assertThat(transitionRepository)
+ .startedTransition(from = KeyguardState.AOD, to = KeyguardState.GONE)
+ }
+
+ @Test
fun testTransitionToOccluded_onWake() =
testScope.runTest {
kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index c8a16483a00c..abcbdb153e80 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -27,6 +27,8 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
import com.android.systemui.Flags
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.Flags.FLAG_COMMUNAL_SCENE_KTF_REFACTOR
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
+import com.android.systemui.Flags.glanceableHubV2
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.communal.domain.interactor.CommunalSceneTransitionInteractor
@@ -34,6 +36,8 @@ import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.communal.domain.interactor.communalSceneTransitionInteractor
import com.android.systemui.communal.domain.interactor.setCommunalAvailable
+import com.android.systemui.communal.domain.interactor.setCommunalV2ConfigEnabled
+import com.android.systemui.communal.domain.interactor.setCommunalV2Enabled
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.flags.BrokenWithSceneContainer
import com.android.systemui.flags.DisableSceneContainer
@@ -153,6 +157,9 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest
if (!SceneContainerFlag.isEnabled) {
mSetFlagsRule.disableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
}
+ if (glanceableHubV2()) {
+ kosmos.setCommunalV2ConfigEnabled(true)
+ }
featureFlags = FakeFeatureFlags()
fromLockscreenTransitionInteractor.start()
@@ -1948,6 +1955,39 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest
@Test
@DisableSceneContainer
+ @EnableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR, FLAG_GLANCEABLE_HUB_V2)
+ fun glanceableHubToDreaming_v2() =
+ testScope.runTest {
+ kosmos.setCommunalV2Enabled(true)
+
+ // GIVEN a device that is not dreaming or dozing
+ keyguardRepository.setDreamingWithOverlay(false)
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+ )
+ advanceTimeBy(600.milliseconds)
+
+ // GIVEN a prior transition has run to glanceable hub
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+ runCurrent()
+ clearInvocations(transitionRepository)
+
+ keyguardRepository.setDreamingWithOverlay(true)
+ advanceTimeBy(100.milliseconds)
+
+ assertThat(transitionRepository)
+ .startedTransition(
+ ownerName = CommunalSceneTransitionInteractor::class.simpleName,
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.DREAMING,
+ animatorAssertion = { it.isNull() },
+ )
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ @DisableSceneContainer
@DisableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR)
fun glanceableHubToDreaming() =
testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
index 9d5bf4dbdc3f..5f5d80c01292 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
@@ -794,6 +794,122 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
TransitionStep(
transitionState = TransitionState.STARTED,
from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ )
+ )
+ runCurrent()
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.RUNNING,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ )
+ )
+ runCurrent()
+
+ assertEquals(
+ listOf(
+ true,
+ // Still not visible during GONE -> LOCKSCREEN.
+ false,
+ ),
+ values,
+ )
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.FINISHED,
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ )
+ )
+ runCurrent()
+
+ assertEquals(
+ listOf(
+ true,
+ false,
+ // Visible now that we're FINISHED in LOCKSCREEN.
+ true,
+ ),
+ values,
+ )
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ )
+ )
+ runCurrent()
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.RUNNING,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ )
+ )
+ runCurrent()
+
+ assertEquals(
+ listOf(
+ true,
+ false,
+ // Remains true until the transition ends.
+ true,
+ ),
+ values,
+ )
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.FINISHED,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ )
+ )
+
+ runCurrent()
+ assertEquals(
+ listOf(
+ true,
+ false,
+ true,
+ // Until we're finished in GONE again.
+ false,
+ ),
+ values,
+ )
+ }
+
+ @Test
+ @DisableSceneContainer
+ fun testLockscreenVisibility_falseDuringWakeAndUnlockToGone_fromNotCanceledGone() =
+ testScope.runTest {
+ val values by collectValues(underTest.value.lockscreenVisibility)
+
+ transitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ testScope,
+ )
+
+ runCurrent()
+ assertEquals(
+ listOf(
+ true,
+ // Not visible when finished in GONE.
+ false,
+ ),
+ values,
+ )
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ from = KeyguardState.GONE,
to = KeyguardState.AOD,
)
)
@@ -857,8 +973,9 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
listOf(
true,
false,
- // Remains visible from AOD during transition.
true,
+ // Becomes false immediately since we're wake and unlocking.
+ false,
),
values,
)
@@ -1045,6 +1162,41 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
assertThat(usingKeyguardGoingAwayAnimation).isFalse()
}
+ @Test
+ fun aodVisibility_visibleFullyInAod_falseOtherwise() =
+ testScope.runTest {
+ val aodVisibility by collectValues(underTest.value.aodVisibility)
+
+ transitionRepository.sendTransitionStepsThroughRunning(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.AOD,
+ testScope,
+ throughValue = 0.5f,
+ )
+
+ assertEquals(listOf(false), aodVisibility)
+
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.FINISHED,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.AOD,
+ )
+ )
+ runCurrent()
+
+ assertEquals(listOf(false, true), aodVisibility)
+
+ transitionRepository.sendTransitionStepsThroughRunning(
+ from = KeyguardState.AOD,
+ to = KeyguardState.GONE,
+ testScope,
+ )
+ runCurrent()
+
+ assertEquals(listOf(false, true, false), aodVisibility)
+ }
+
companion object {
private val progress = MutableStateFlow(0f)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
index 286f8bfd63a2..e93ed39274fb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
@@ -20,6 +20,7 @@ import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_BOUNCER_UI_REVAMP
+import com.android.systemui.Flags.FLAG_NOTIFICATION_SHADE_BLUR
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.BrokenWithSceneContainer
@@ -97,6 +98,7 @@ class AlternateBouncerToPrimaryBouncerTransitionViewModelTest : SysuiTestCase()
}
@Test
+ @EnableFlags(FLAG_NOTIFICATION_SHADE_BLUR)
fun blurRadiusGoesToMaximumWhenShadeIsExpanded() =
testScope.runTest {
val values by collectValues(underTest.windowBlurRadius)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelTest.kt
new file mode 100644
index 000000000000..b4d546d2a8bb
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelTest.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.keyguard.ui.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DozingToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val configurationRepository = kosmos.fakeConfigurationRepository
+ val underTest by lazy { kosmos.dozingToGlanceableHubTransitionViewModel }
+
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMaxValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = blurConfig.minBlurRadiusPx,
+ endValue = blurConfig.maxBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.DOZING,
+ to = KeyguardState.GLANCEABLE_HUB,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "DozingToGlanceableHubTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt
index cd0a11c08f33..cf86c2544941 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt
@@ -23,16 +23,19 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
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.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
@@ -49,11 +52,11 @@ class DreamingToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
@Test
fun dreamOverlayAlpha() =
- testScope.runTest {
+ kosmos.runTest {
val values by collectValues(underTest.dreamOverlayAlpha)
assertThat(values).isEmpty()
- kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
listOf(
// Should start running here...
step(0f, TransitionState.STARTED),
@@ -72,10 +75,10 @@ class DreamingToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
@Test
fun dreamOverlayTranslationX() =
- testScope.runTest {
+ kosmos.runTest {
configurationRepository.setDimensionPixelSize(
R.dimen.dreaming_to_hub_transition_dream_overlay_translation_x,
- -100
+ -100,
)
val configuration: Configuration = mock()
whenever(configuration.layoutDirection).thenReturn(LayoutDirection.LTR)
@@ -84,12 +87,8 @@ class DreamingToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
val values by collectValues(underTest.dreamOverlayTranslationX)
assertThat(values).isEmpty()
- kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
- listOf(
- step(0f, TransitionState.STARTED),
- step(0.3f),
- step(0.6f),
- ),
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
+ listOf(step(0f, TransitionState.STARTED), step(0.3f), step(0.6f)),
testScope,
)
@@ -97,16 +96,40 @@ class DreamingToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) }
}
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMaxValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = blurConfig.minBlurRadiusPx,
+ endValue = blurConfig.maxBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.GLANCEABLE_HUB,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "DreamingToGlanceableHubTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+
private fun step(
value: Float,
- state: TransitionState = TransitionState.RUNNING
+ state: TransitionState = TransitionState.RUNNING,
): TransitionStep {
return TransitionStep(
from = KeyguardState.DREAMING,
to = KeyguardState.GLANCEABLE_HUB,
value = value,
transitionState = state,
- ownerName = "DreamingToGlanceableHubTransitionViewModelTest"
+ ownerName = "DreamingToGlanceableHubTransitionViewModelTest",
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelTest.kt
new file mode 100644
index 000000000000..eb01681b1aea
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelTest.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.keyguard.ui.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class GlanceableHubToDozingTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val configurationRepository = kosmos.fakeConfigurationRepository
+ val underTest by lazy { kosmos.glanceableHubToDozingTransitionViewModel }
+
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMinValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = kosmos.blurConfig.maxBlurRadiusPx,
+ endValue = kosmos.blurConfig.minBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.DOZING,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "GlanceableHubToDozingTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt
index 69361efc7e06..dd9563f52a43 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelTest.kt
@@ -22,17 +22,19 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
-import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
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.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
@@ -49,11 +51,11 @@ class GlanceableHubToDreamingTransitionViewModelTest : SysuiTestCase() {
@Test
fun dreamOverlayAlpha() =
- testScope.runTest {
+ kosmos.runTest {
val values by collectValues(underTest.dreamOverlayAlpha)
assertThat(values).isEmpty()
- kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
listOf(
step(0f, TransitionState.STARTED),
step(0f),
@@ -72,24 +74,20 @@ class GlanceableHubToDreamingTransitionViewModelTest : SysuiTestCase() {
@Test
fun dreamOverlayTranslationX() =
- testScope.runTest {
+ kosmos.runTest {
val config: Configuration = mock()
whenever(config.layoutDirection).thenReturn(LayoutDirection.LTR)
configurationRepository.onConfigurationChange(config)
configurationRepository.setDimensionPixelSize(
R.dimen.hub_to_dreaming_transition_dream_overlay_translation_x,
- 100
+ 100,
)
val values by collectValues(underTest.dreamOverlayTranslationX)
assertThat(values).isEmpty()
- kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
- listOf(
- step(0f, TransitionState.STARTED),
- step(0.3f),
- step(0.6f),
- ),
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
+ listOf(step(0f, TransitionState.STARTED), step(0.3f), step(0.6f)),
testScope,
)
@@ -97,16 +95,40 @@ class GlanceableHubToDreamingTransitionViewModelTest : SysuiTestCase() {
values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) }
}
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMinValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = blurConfig.maxBlurRadiusPx,
+ endValue = blurConfig.minBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.DREAMING,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "GlanceableHubToDreamingTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+
private fun step(
value: Float,
- state: TransitionState = TransitionState.RUNNING
+ state: TransitionState = TransitionState.RUNNING,
): TransitionStep {
return TransitionStep(
from = KeyguardState.GLANCEABLE_HUB,
to = KeyguardState.DREAMING,
value = value,
transitionState = state,
- ownerName = GlanceableHubToDreamingTransitionViewModelTest::class.java.simpleName
+ ownerName = GlanceableHubToDreamingTransitionViewModelTest::class.java.simpleName,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt
index d2be6495be18..1dd435b413be 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt
@@ -22,18 +22,20 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
-import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
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.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
@@ -52,7 +54,7 @@ class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
@Test
fun lockscreenFadeIn() =
- testScope.runTest {
+ kosmos.runTest {
val values by collectValues(underTest.keyguardAlpha)
assertThat(values).isEmpty()
@@ -80,14 +82,14 @@ class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
@Test
fun lockscreenTranslationX() =
- testScope.runTest {
+ kosmos.runTest {
val config: Configuration = mock()
whenever(config.layoutDirection).thenReturn(LayoutDirection.LTR)
configurationRepository.onConfigurationChange(config)
configurationRepository.setDimensionPixelSize(
R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x,
- 100
+ 100,
)
val values by collectValues(underTest.keyguardTranslationX)
assertThat(values).isEmpty()
@@ -109,14 +111,14 @@ class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
@Test
fun lockscreenTranslationX_resetsAfterCancellation() =
- testScope.runTest {
+ kosmos.runTest {
val config: Configuration = mock()
whenever(config.layoutDirection).thenReturn(LayoutDirection.LTR)
configurationRepository.onConfigurationChange(config)
configurationRepository.setDimensionPixelSize(
R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x,
- 100
+ 100,
)
val values by collectValues(underTest.keyguardTranslationX)
assertThat(values).isEmpty()
@@ -126,7 +128,7 @@ class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
step(0f, TransitionState.STARTED),
step(0.3f),
step(0.5f),
- step(0.9f, TransitionState.CANCELED)
+ step(0.9f, TransitionState.CANCELED),
),
testScope,
)
@@ -136,16 +138,40 @@ class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
assertThat(values.last().value).isEqualTo(0f)
}
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMinValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = blurConfig.maxBlurRadiusPx,
+ endValue = blurConfig.minBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.LOCKSCREEN,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "GlanceableHubToLockscreenTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+
private fun step(
value: Float,
- state: TransitionState = TransitionState.RUNNING
+ state: TransitionState = TransitionState.RUNNING,
): TransitionStep {
return TransitionStep(
from = KeyguardState.GLANCEABLE_HUB,
to = KeyguardState.LOCKSCREEN,
value = value,
transitionState = state,
- ownerName = this::class.java.simpleName
+ ownerName = this::class.java.simpleName,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelTest.kt
new file mode 100644
index 000000000000..7eca17d82194
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.keyguard.ui.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class GlanceableHubToOccludedTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
+ val underTest by lazy { kosmos.glanceableHubToOccludedTransitionViewModel }
+
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMinValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = blurConfig.maxBlurRadiusPx,
+ endValue = blurConfig.minBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.OCCLUDED,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "GlanceableHubToOccludedTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt
index abf8b39ce5af..54d20d203fc1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt
@@ -16,18 +16,20 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.transitions.blurConfig
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
import com.android.systemui.testKosmos
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@@ -36,19 +38,19 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class GlanceableHubToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
private val underTest by lazy { kosmos.glanceableHubToPrimaryBouncerTransitionViewModel }
@Test
@DisableSceneContainer
+ @DisableFlags(FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND)
fun blurBecomesMaxValueImmediately() =
- testScope.runTest {
+ kosmos.runTest {
val values by collectValues(underTest.windowBlurRadius)
kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
- startValue = kosmos.blurConfig.maxBlurRadiusPx,
- endValue = kosmos.blurConfig.maxBlurRadiusPx,
+ startValue = blurConfig.maxBlurRadiusPx,
+ endValue = blurConfig.maxBlurRadiusPx,
actualValuesProvider = { values },
transitionFactory = { step, transitionState ->
TransitionStep(
@@ -62,4 +64,26 @@ class GlanceableHubToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
checkInterpolatedValues = false,
)
}
+
+ @Test
+ @DisableSceneContainer
+ @EnableFlags(FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND)
+ fun noBlurTransitionWithBlurredGlanceableHub() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertNoBlurRadiusTransition(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "GlanceableHubToPrimaryBouncerTransitionViewModelTest",
+ )
+ },
+ )
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
index aab46d8cb73a..724d4c022fb2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt
@@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.testKosmos
import org.junit.Before
import org.junit.Test
@@ -46,6 +47,7 @@ class KeyguardBlueprintViewModelTest : SysuiTestCase() {
handler = kosmos.fakeExecutorHandler,
keyguardBlueprintInteractor = keyguardBlueprintInteractor,
keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
+ blueprintLog = logcatLogBuffer("blueprints"),
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardWindowBlurTestUtilKosmos.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardWindowBlurTestUtilKosmos.kt
index ef07786284c9..802885cac538 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardWindowBlurTestUtilKosmos.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardWindowBlurTestUtilKosmos.kt
@@ -76,6 +76,21 @@ class KeyguardWindowBlurTestUtil(
}
}
+ suspend fun assertNoBlurRadiusTransition(
+ transitionProgress: List<Float>,
+ actualValuesProvider: () -> List<Float>,
+ transitionFactory: (value: Float, state: TransitionState) -> TransitionStep,
+ ) {
+ val transitionSteps =
+ listOf(
+ transitionFactory(transitionProgress.first(), STARTED),
+ *transitionProgress.drop(1).map { transitionFactory(it, RUNNING) }.toTypedArray(),
+ )
+ fakeKeyguardTransitionRepository.sendTransitionSteps(transitionSteps, testScope)
+
+ assertThat(actualValuesProvider.invoke()).isEmpty()
+ }
+
fun shadeExpanded(expanded: Boolean) {
if (expanded) {
shadeTestUtil.setQsExpansion(1f)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
index e4eb55b79a23..5436d7eee00c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.ui.viewmodel
-import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -37,7 +36,7 @@ import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.testKosmos
import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
import com.android.systemui.util.mockito.whenever
@@ -134,11 +133,11 @@ class LockscreenContentViewModelTest(flags: FlagsParameterization) : SysuiTestCa
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun areNotificationsVisible_dualShadeWideOnLockscreen_true() =
with(kosmos) {
testScope.runTest {
val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible())
+ kosmos.enableDualShade()
shadeRepository.setShadeLayoutWide(true)
fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt
index a60a486daf71..b5cee80c0bf6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt
@@ -22,21 +22,22 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
-import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
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.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito.mock
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
@@ -53,7 +54,7 @@ class LockscreenToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
@Test
fun lockscreenFadeOut() =
- testScope.runTest {
+ kosmos.runTest {
val values by collectValues(underTest.keyguardAlpha)
assertThat(values).isEmpty()
@@ -82,10 +83,10 @@ class LockscreenToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
@Test
fun lockscreenTranslationX() =
- testScope.runTest {
+ kosmos.runTest {
configurationRepository.setDimensionPixelSize(
R.dimen.lockscreen_to_hub_transition_lockscreen_translation_x,
- -100
+ -100,
)
val configuration = mock<Configuration>()
whenever(configuration.layoutDirection).thenReturn(LayoutDirection.LTR)
@@ -108,16 +109,40 @@ class LockscreenToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
values.forEach { assertThat(it.value).isIn(Range.closed(-100f, 0f)) }
}
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMaxValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = blurConfig.minBlurRadiusPx,
+ endValue = blurConfig.maxBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GLANCEABLE_HUB,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "LockscreenToGlanceableHubTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+
private fun step(
value: Float,
- state: TransitionState = TransitionState.RUNNING
+ state: TransitionState = TransitionState.RUNNING,
): TransitionStep {
return TransitionStep(
from = KeyguardState.LOCKSCREEN,
to = KeyguardState.GLANCEABLE_HUB,
value = value,
transitionState = state,
- ownerName = this::class.java.simpleName
+ ownerName = this::class.java.simpleName,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
index 60a19a4c7d07..aaca603ecf77 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
@@ -21,6 +21,7 @@ import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.Flags.FLAG_BOUNCER_UI_REVAMP
+import com.android.systemui.Flags.FLAG_NOTIFICATION_SHADE_BLUR
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
@@ -155,6 +156,7 @@ class LockscreenToPrimaryBouncerTransitionViewModelTest(flags: FlagsParameteriza
}
@Test
+ @EnableFlags(FLAG_NOTIFICATION_SHADE_BLUR)
@BrokenWithSceneContainer(388068805)
fun blurRadiusIsMaxWhenShadeIsExpanded() =
testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelTest.kt
new file mode 100644
index 000000000000..c657bddca9a0
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.keyguard.ui.transitions.blurConfig
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class OccludedToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
+ val underTest by lazy { kosmos.occludedToGlanceableHubTransitionViewModel }
+
+ @Test
+ @DisableSceneContainer
+ fun blurBecomesMaxValueImmediately() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = blurConfig.minBlurRadiusPx,
+ endValue = blurConfig.maxBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.GLANCEABLE_HUB,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "OccludedToGlanceableHubTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelTest.kt
index 6db876756d3a..0951df24c56f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelTest.kt
@@ -16,50 +16,96 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_NOTIFICATION_SHADE_BLUR
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.BrokenWithSceneContainer
+import com.android.systemui.flags.andSceneContainer
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.transitions.blurConfig
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@ExperimentalCoroutinesApi
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class OccludedToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class OccludedToPrimaryBouncerTransitionViewModelTest(flags: FlagsParameterization) :
+ SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val underTest by lazy { kosmos.occludedToPrimaryBouncerTransitionViewModel }
+ private lateinit var underTest: OccludedToPrimaryBouncerTransitionViewModel
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags)
+ }
+
+ @Before
+ fun setup() {
+ underTest = kosmos.occludedToPrimaryBouncerTransitionViewModel
+ }
@Test
- @DisableSceneContainer
- fun blurBecomesMaxValueImmediately() =
+ @BrokenWithSceneContainer(388068805)
+ fun notificationsAreBlurredImmediatelyWhenBouncerIsOpenedAndShadeIsExpanded() =
+ testScope.runTest {
+ val values by collectValues(underTest.notificationBlurRadius)
+ kosmos.keyguardWindowBlurTestUtil.shadeExpanded(true)
+
+ kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = kosmos.blurConfig.maxBlurRadiusPx,
+ endValue = kosmos.blurConfig.maxBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = ::step,
+ checkInterpolatedValues = false,
+ )
+ }
+
+ @Test
+ @EnableFlags(FLAG_NOTIFICATION_SHADE_BLUR)
+ @BrokenWithSceneContainer(388068805)
+ fun blurBecomesMaxValueImmediatelyWhenShadeIsAlreadyExpanded() =
testScope.runTest {
val values by collectValues(underTest.windowBlurRadius)
+ kosmos.keyguardWindowBlurTestUtil.shadeExpanded(true)
kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
startValue = kosmos.blurConfig.maxBlurRadiusPx,
endValue = kosmos.blurConfig.maxBlurRadiusPx,
actualValuesProvider = { values },
- transitionFactory = { step, transitionState ->
- TransitionStep(
- from = KeyguardState.OCCLUDED,
- to = KeyguardState.PRIMARY_BOUNCER,
- value = step,
- transitionState = transitionState,
- ownerName = "OccludedToPrimaryBouncerTransitionViewModelTest",
- )
- },
+ transitionFactory = ::step,
checkInterpolatedValues = false,
)
}
+
+ fun step(value: Float, state: TransitionState = TransitionState.RUNNING): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ value = value,
+ transitionState = state,
+ ownerName = "OccludedToPrimaryBouncerTransitionViewModelTest",
+ )
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt
index 9cfcce43d13d..e4843bd88133 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt
@@ -16,18 +16,20 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.transitions.blurConfig
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
import com.android.systemui.testKosmos
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@@ -36,19 +38,19 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class PrimaryBouncerToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
private val underTest by lazy { kosmos.primaryBouncerToGlanceableHubTransitionViewModel }
@Test
@DisableSceneContainer
+ @DisableFlags(FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND)
fun blurBecomesMinValueImmediately() =
- testScope.runTest {
+ kosmos.runTest {
val values by collectValues(underTest.windowBlurRadius)
- kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
- startValue = kosmos.blurConfig.minBlurRadiusPx,
- endValue = kosmos.blurConfig.minBlurRadiusPx,
+ startValue = blurConfig.maxBlurRadiusPx,
+ endValue = blurConfig.minBlurRadiusPx,
actualValuesProvider = { values },
transitionFactory = { step, transitionState ->
TransitionStep(
@@ -62,4 +64,26 @@ class PrimaryBouncerToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
checkInterpolatedValues = false,
)
}
+
+ @Test
+ @DisableSceneContainer
+ @EnableFlags(FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND)
+ fun noBlurTransitionWithBlurredGlanceableHub() =
+ kosmos.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+
+ keyguardWindowBlurTestUtil.assertNoBlurRadiusTransition(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.PRIMARY_BOUNCER,
+ to = KeyguardState.GLANCEABLE_HUB,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "PrimaryBouncerToGlanceableHubTransitionViewModelTest",
+ )
+ },
+ )
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
index 0db0c5fe8482..8fefb8d40b71 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
@@ -16,12 +16,16 @@
package com.android.systemui.keyguard.ui.viewmodel
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_NOTIFICATION_SHADE_BLUR
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.BrokenWithSceneContainer
+import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -35,13 +39,17 @@ import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@ExperimentalCoroutinesApi
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class PrimaryBouncerToLockscreenTransitionViewModelTest(flags: FlagsParameterization) :
+ SysuiTestCase() {
val kosmos = testKosmos()
val testScope = kosmos.testScope
@@ -49,9 +57,27 @@ class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
val biometricSettingsRepository = kosmos.biometricSettingsRepository
- val underTest = kosmos.primaryBouncerToLockscreenTransitionViewModel
+ private lateinit var underTest: PrimaryBouncerToLockscreenTransitionViewModel
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags)
+ }
+
+ @Before
+ fun setup() {
+ underTest = kosmos.primaryBouncerToLockscreenTransitionViewModel
+ }
@Test
+ @BrokenWithSceneContainer(392346450)
fun lockscreenAlphaStartsFromViewStateAccessorAlpha() =
testScope.runTest {
val viewState = ViewStateAccessor(alpha = { 0.5f })
@@ -70,6 +96,7 @@ class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
}
@Test
+ @BrokenWithSceneContainer(392346450)
fun deviceEntryParentViewAlpha() =
testScope.runTest {
val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha)
@@ -89,6 +116,7 @@ class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
}
@Test
+ @BrokenWithSceneContainer(392346450)
fun deviceEntryBackgroundViewAlpha_udfpsEnrolled_show() =
testScope.runTest {
fingerprintPropertyRepository.supportsUdfps()
@@ -113,6 +141,7 @@ class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
}
@Test
+ @BrokenWithSceneContainer(388068805)
fun blurRadiusGoesFromMaxToMinWhenShadeIsNotExpanded() =
testScope.runTest {
val values by collectValues(underTest.windowBlurRadius)
@@ -128,6 +157,8 @@ class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(FLAG_NOTIFICATION_SHADE_BLUR)
+ @BrokenWithSceneContainer(388068805)
fun blurRadiusRemainsAtMaxWhenShadeIsExpanded() =
testScope.runTest {
val values by collectValues(underTest.windowBlurRadius)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelTest.kt
index b0b4af5fea5b..fd7fb9f863c8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelTest.kt
@@ -16,11 +16,13 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.BrokenWithSceneContainer
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.transitions.blurConfig
@@ -40,10 +42,37 @@ class PrimaryBouncerToOccludedTransitionViewModelTest : SysuiTestCase() {
private val underTest by lazy { kosmos.primaryBouncerToOccludedTransitionViewModel }
@Test
- @DisableSceneContainer
- fun blurBecomesMaxValueImmediately() =
+ @BrokenWithSceneContainer(388068805)
+ fun blurBecomesMinValueImmediatelyWhenShadeIsNotExpanded() =
testScope.runTest {
val values by collectValues(underTest.windowBlurRadius)
+ kosmos.keyguardWindowBlurTestUtil.shadeExpanded(false)
+
+ kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
+ transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
+ startValue = kosmos.blurConfig.minBlurRadiusPx,
+ endValue = kosmos.blurConfig.minBlurRadiusPx,
+ actualValuesProvider = { values },
+ transitionFactory = { step, transitionState ->
+ TransitionStep(
+ from = KeyguardState.PRIMARY_BOUNCER,
+ to = KeyguardState.OCCLUDED,
+ value = step,
+ transitionState = transitionState,
+ ownerName = "PrimaryBouncerToOccludedTransitionViewModelTest",
+ )
+ },
+ checkInterpolatedValues = false,
+ )
+ }
+
+ @Test
+ @BrokenWithSceneContainer(388068805)
+ @EnableFlags(Flags.FLAG_NOTIFICATION_SHADE_BLUR)
+ fun blurBecomesMaxValueImmediatelyWhenShadeIsExpanded() =
+ testScope.runTest {
+ val values by collectValues(underTest.windowBlurRadius)
+ kosmos.keyguardWindowBlurTestUtil.shadeExpanded(false)
kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaDataRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaDataRepositoryTest.kt
index 2864f041e451..7e6f5fc71b15 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaDataRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaDataRepositoryTest.kt
@@ -22,8 +22,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.MediaTestHelper
import com.android.systemui.media.controls.shared.model.MediaData
@@ -79,29 +77,6 @@ class MediaDataRepositoryTest : SysuiTestCase() {
}
@Test
- fun setRecommendationInactive() =
- testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, true)
- val smartspaceData by collectLastValue(underTest.smartspaceMediaData)
- val icon = Icon.createWithResource(context, R.drawable.ic_media_play)
- val recommendation =
- SmartspaceMediaData(
- targetId = KEY_MEDIA_SMARTSPACE,
- isActive = true,
- recommendations = MediaTestHelper.getValidRecommendationList(icon),
- )
-
- underTest.setRecommendation(recommendation)
-
- assertThat(smartspaceData).isEqualTo(recommendation)
-
- underTest.setRecommendationInactive(KEY_MEDIA_SMARTSPACE)
-
- assertThat(smartspaceData).isNotEqualTo(recommendation)
- assertThat(smartspaceData!!.isActive).isFalse()
- }
-
- @Test
fun dismissRecommendation() =
testScope.runTest {
val smartspaceData by collectLastValue(underTest.smartspaceMediaData)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
index 414974cc2941..0a44e7b5b1ed 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
@@ -24,8 +24,6 @@ import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.MediaTestHelper
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
@@ -140,7 +138,6 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
val hasAnyMediaOrRecommendation by
collectLastValue(underTest.hasAnyMediaOrRecommendation)
val currentMedia by collectLastValue(underTest.currentMedia)
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
val userMedia = MediaData(active = false)
val recsLoadingModel = SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
@@ -163,7 +160,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
assertThat(currentMedia)
.containsExactly(
MediaCommonModel.MediaRecommendations(recsLoadingModel),
- MediaCommonModel.MediaControl(mediaLoadingModel, true)
+ MediaCommonModel.MediaControl(mediaLoadingModel, true),
)
.inOrder()
@@ -176,7 +173,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
Process.INVALID_UID,
surface = SURFACE,
2,
- true
+ true,
)
}
@@ -187,7 +184,6 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
collectLastValue(underTest.hasActiveMediaOrRecommendation)
val hasAnyMediaOrRecommendation by
collectLastValue(underTest.hasAnyMediaOrRecommendation)
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
mediaFilterRepository.setRecommendation(mediaRecommendation)
@@ -207,7 +203,6 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
collectLastValue(underTest.hasActiveMediaOrRecommendation)
val hasAnyMediaOrRecommendation by
collectLastValue(underTest.hasAnyMediaOrRecommendation)
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
mediaFilterRepository.setRecommendation(mediaRecommendation)
@@ -248,7 +243,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
active = true,
instanceId = instanceId,
packageName = PACKAGE_NAME,
- notificationKey = KEY
+ notificationKey = KEY,
)
val smartspaceLoadingModel = SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE)
val mediaLoadingModel = MediaDataLoadingModel.Loaded(instanceId)
@@ -269,7 +264,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
assertThat(currentMedia)
.containsExactly(
MediaCommonModel.MediaControl(mediaLoadingModel, isMediaFromRec = true),
- MediaCommonModel.MediaRecommendations(smartspaceLoadingModel)
+ MediaCommonModel.MediaRecommendations(smartspaceLoadingModel),
)
.inOrder()
}
@@ -282,7 +277,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
active = true,
instanceId = instanceId,
packageName = PACKAGE_NAME,
- notificationKey = KEY
+ notificationKey = KEY,
)
val smartspaceLoadingModel = SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE)
val mediaLoadingModel = MediaDataLoadingModel.Loaded(instanceId)
@@ -297,7 +292,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
data.smartspaceId,
data.appUid,
surface = SURFACE,
- 1
+ 1,
)
reset(smartspaceLogger)
@@ -311,7 +306,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
data.smartspaceId,
data.appUid,
surface = SURFACE,
- 2
+ 2,
)
reset(smartspaceLogger)
@@ -327,7 +322,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
surface = SURFACE,
2,
true,
- rank = 1
+ rank = 1,
)
reset(smartspaceLogger)
@@ -343,7 +338,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
data.smartspaceId,
data.appUid,
surface = SURFACE,
- 2
+ 2,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaRecommendationsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaRecommendationsInteractorTest.kt
index 8af7e1dbe59b..11397d99bc03 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaRecommendationsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaRecommendationsInteractorTest.kt
@@ -29,8 +29,6 @@ import com.android.systemui.animation.Expandable
import com.android.systemui.broadcast.broadcastSender
import com.android.systemui.broadcast.mockBroadcastSender
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.MediaTestHelper
import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl
@@ -104,8 +102,8 @@ class MediaRecommendationsInteractorTest : SysuiTestCase() {
listOf(
MediaRecModel(icon = icon),
MediaRecModel(icon = icon),
- MediaRecModel(icon = icon)
- )
+ MediaRecModel(icon = icon),
+ ),
)
mediaDataFilter.onSmartspaceMediaDataLoaded(KEY_MEDIA_SMARTSPACE, smartspaceMediaData)
@@ -114,22 +112,6 @@ class MediaRecommendationsInteractorTest : SysuiTestCase() {
}
@Test
- fun setRecommendationInactive_isActiveUpdate() =
- testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, true)
- val isActive by collectLastValue(underTest.isActive)
-
- mediaDataFilter.onSmartspaceMediaDataLoaded(KEY_MEDIA_SMARTSPACE, smartspaceMediaData)
- assertThat(isActive).isTrue()
-
- mediaDataFilter.onSmartspaceMediaDataLoaded(
- KEY_MEDIA_SMARTSPACE,
- smartspaceMediaData.copy(isActive = false)
- )
- assertThat(isActive).isFalse()
- }
-
- @Test
fun addInvalidRecommendation() =
testScope.runTest {
val recommendations by collectLastValue(underTest.recommendations)
@@ -155,7 +137,7 @@ class MediaRecommendationsInteractorTest : SysuiTestCase() {
intent,
0,
SMARTSPACE_CARD_DISMISS_EVENT,
- 1
+ 1,
)
verify(smartspaceLogger)
@@ -183,7 +165,7 @@ class MediaRecommendationsInteractorTest : SysuiTestCase() {
intent,
0,
SMARTSPACE_CARD_DISMISS_EVENT,
- 1
+ 1,
)
verify(spyContext).startActivity(eq(intent))
@@ -216,7 +198,7 @@ class MediaRecommendationsInteractorTest : SysuiTestCase() {
cardinality = 1,
isRecommendationCard = true,
interactedSubcardRank = 2,
- interactedSubcardCardinality = 3
+ interactedSubcardCardinality = 3,
)
verify(spyContext).startActivity(eq(intent))
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
index 51c852531697..a3b3f5c6845d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
@@ -96,7 +96,6 @@ class MediaTimeoutListenerTest : SysuiTestCase() {
@Before
fun setup() {
whenever(mediaControllerFactory.create(any())).thenReturn(mediaController)
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
mainExecutor = FakeExecutor(clock)
bgExecutor = FakeExecutor(clock)
uiExecutor = FakeExecutor(clock)
@@ -612,89 +611,6 @@ class MediaTimeoutListenerTest : SysuiTestCase() {
assertThat(mainExecutor.numPending()).isEqualTo(1)
}
- @Test
- fun testSmartspaceDataLoaded_schedulesTimeout() {
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- val duration = 60_000
- val createTime = 1234L
- val expireTime = createTime + duration
- whenever(smartspaceData.headphoneConnectionTimeMillis).thenReturn(createTime)
- whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
-
- mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(mainExecutor.numPending()).isEqualTo(1)
- assertThat(mainExecutor.advanceClockToNext()).isEqualTo(duration)
- }
-
- @Test
- fun testSmartspaceMediaData_timesOut_invokesCallback() {
- // Given a pending timeout
- testSmartspaceDataLoaded_schedulesTimeout()
-
- mainExecutor.runAllReady()
- verify(timeoutCallback).invoke(eq(SMARTSPACE_KEY), eq(true))
- }
-
- @Test
- fun testSmartspaceDataLoaded_alreadyExists_updatesTimeout() {
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- val duration = 100
- val createTime = 1234L
- val expireTime = createTime + duration
- whenever(smartspaceData.headphoneConnectionTimeMillis).thenReturn(createTime)
- whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
-
- mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(mainExecutor.numPending()).isEqualTo(1)
-
- val expiryLonger = expireTime + duration
- whenever(smartspaceData.expiryTimeMs).thenReturn(expiryLonger)
- mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-
- assertThat(mainExecutor.numPending()).isEqualTo(1)
- assertThat(mainExecutor.advanceClockToNext()).isEqualTo(duration * 2)
- }
-
- @Test
- fun testSmartspaceDataRemoved_cancelTimeout() {
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
-
- mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(mainExecutor.numPending()).isEqualTo(1)
-
- mediaTimeoutListener.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
- assertThat(mainExecutor.numPending()).isEqualTo(0)
- }
-
- @Test
- fun testSmartspaceData_dozedPastTimeout_invokedOnWakeup() {
- // Given a pending timeout
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- verify(statusBarStateController).addCallback(capture(dozingCallbackCaptor))
- val duration = 60_000
- val createTime = 1234L
- val expireTime = createTime + duration
- whenever(smartspaceData.headphoneConnectionTimeMillis).thenReturn(createTime)
- whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
-
- mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(mainExecutor.numPending()).isEqualTo(1)
-
- // And we doze past the scheduled timeout
- val time = clock.currentTimeMillis()
- clock.setElapsedRealtime(time + duration * 2)
- assertThat(mainExecutor.numPending()).isEqualTo(1)
-
- // Then when no longer dozing, the timeout runs immediately
- dozingCallbackCaptor.value.onDozingChanged(false)
- verify(timeoutCallback).invoke(eq(SMARTSPACE_KEY), eq(true))
- verify(logger).logTimeout(eq(SMARTSPACE_KEY))
-
- // and cancel any later scheduled timeout
- assertThat(mainExecutor.numPending()).isEqualTo(0)
- }
-
private fun loadMediaDataWithPlaybackState(state: PlaybackState) {
whenever(mediaController.playbackState).thenReturn(state)
loadMediaData(data = mediaData)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt
index 067b00c1658b..fb5bbf452cfa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelTest.kt
@@ -25,8 +25,6 @@ import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.MediaTestHelper
import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl
@@ -126,7 +124,6 @@ class MediaCarouselViewModelTest : SysuiTestCase() {
fun loadMediaControlsAndRecommendations_mediaItemsAreUpdated() =
testScope.runTest {
val sortedMedia by collectLastValue(underTest.mediaItems)
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
val instanceId1 = InstanceId.fakeInstanceId(123)
val instanceId2 = InstanceId.fakeInstanceId(456)
@@ -147,7 +144,6 @@ class MediaCarouselViewModelTest : SysuiTestCase() {
testScope.runTest {
val sortedMedia by collectLastValue(underTest.mediaItems)
kosmos.visualStabilityProvider.isReorderingAllowed = false
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
val instanceId = InstanceId.fakeInstanceId(123)
loadMediaRecommendations()
@@ -207,7 +203,6 @@ class MediaCarouselViewModelTest : SysuiTestCase() {
fun addMediaRecommendationThenRemove_mediaEventsAreLogged() =
testScope.runTest {
val sortedMedia by collectLastValue(underTest.mediaItems)
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
loadMediaRecommendations()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 63ec78fd9ee5..7478464772a4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -156,11 +156,10 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTitleText.getText()).isEqualTo(mContext.getText(
- R.string.media_output_dialog_pairing_new));
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
+ mContext.getText(R.string.media_output_dialog_pairing_new).toString());
}
@Test
@@ -179,7 +178,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
@@ -201,7 +199,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
@@ -216,7 +213,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -232,7 +228,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -250,7 +245,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -265,7 +259,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
assertThat(mViewHolder.mSeekBar.getContentDescription()).isNotNull();
- assertThat(mViewHolder.mSeekBar.getAccessibilityDelegate()).isNotNull();
assertThat(mViewHolder.mContainerLayout.isFocusable()).isFalse();
}
@@ -282,7 +275,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.GONE);
}
@@ -302,7 +294,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -324,7 +315,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -335,7 +325,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(false);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -351,7 +340,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
.onCreateViewHolder(new LinearLayout(mContext), 0);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -393,7 +381,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
when(mMediaSwitchingController.getSelectableMediaDevice()).thenReturn(selectableDevices);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -405,7 +392,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
public void onBindViewHolder_bindNonActiveConnectedDevice_verifyView() {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -423,7 +409,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
TEST_DEVICE_NAME_2);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -432,15 +417,14 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(mContext.getText(
- R.string.media_output_dialog_connect_failed));
- assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
+ assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(
+ mContext.getText(R.string.media_output_dialog_connect_failed).toString());
}
@Test
@@ -456,17 +440,15 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
.onCreateViewHolder(new LinearLayout(mContext), 0);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(TEST_CUSTOM_SUBTEXT);
- assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
- TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isFalse();
}
@@ -482,15 +464,14 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
.onCreateViewHolder(new LinearLayout(mContext), 0);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(deviceStatus);
- assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
+ assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(deviceStatus);
assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isTrue();
}
@@ -506,16 +487,14 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
.onCreateViewHolder(new LinearLayout(mContext), 0);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(deviceStatus);
- assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
- TEST_DEVICE_NAME_2);
assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isFalse();
}
@@ -530,16 +509,14 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
.onCreateViewHolder(new LinearLayout(mContext), 0);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(TEST_CUSTOM_SUBTEXT);
- assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
- TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isFalse();
}
@@ -556,7 +533,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -572,7 +548,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -582,11 +557,10 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mViewHolder.mTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/OWNERS b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/OWNERS
new file mode 100644
index 000000000000..739d2ac2e87b
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/dialog/OWNERS
@@ -0,0 +1 @@
+file:/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
index a770ee199ba6..c1872f05aa1d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -57,7 +57,7 @@ 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.recents.LauncherProxyService;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
@@ -104,7 +104,7 @@ public class NavBarHelperTest extends SysuiTestCase {
@Mock
SystemActions mSystemActions;
@Mock
- OverviewProxyService mOverviewProxyService;
+ LauncherProxyService mLauncherProxyService;
@Mock
Lazy<AssistManager> mAssistManagerLazy;
@Mock
@@ -161,7 +161,7 @@ public class NavBarHelperTest extends SysuiTestCase {
mNavBarHelper = new NavBarHelper(mContext, mAccessibilityManager,
mAccessibilityButtonModeObserver, mAccessibilityButtonTargetObserver,
mAccessibilityGestureTargetObserver,
- mSystemActions, mOverviewProxyService, mAssistManagerLazy,
+ mSystemActions, mLauncherProxyService, mAssistManagerLazy,
() -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class),
mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker,
mDisplayTracker, mNotificationShadeWindowController, mConfigurationController,
@@ -171,7 +171,7 @@ public class NavBarHelperTest extends SysuiTestCase {
@Test
public void registerListenersInCtor() {
verify(mNavigationModeController, times(1)).addListener(mNavBarHelper);
- verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper);
+ verify(mLauncherProxyService, times(1)).addCallback(mNavBarHelper);
verify(mCommandQueue, times(1)).addCallback(any());
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
index 9bae7bd72f7d..cf0a25020d93 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
@@ -9,7 +9,7 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.model.SysUiState
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.LauncherProxyService
import com.android.systemui.settings.DisplayTracker
import com.android.systemui.shared.system.QuickStepContract
import com.android.systemui.shared.system.TaskStackChangeListeners
@@ -49,7 +49,7 @@ class TaskbarDelegateTest : SysuiTestCase() {
@Mock lateinit var mLightBarControllerFactory: LightBarTransitionsController.Factory
@Mock lateinit var mLightBarTransitionController: LightBarTransitionsController
@Mock lateinit var mCommandQueue: CommandQueue
- @Mock lateinit var mOverviewProxyService: OverviewProxyService
+ @Mock lateinit var mLauncherProxyService: LauncherProxyService
@Mock lateinit var mNavBarHelper: NavBarHelper
@Mock lateinit var mNavigationModeController: NavigationModeController
@Mock lateinit var mSysUiState: SysUiState
@@ -87,7 +87,7 @@ class TaskbarDelegateTest : SysuiTestCase() {
)
mTaskbarDelegate.setDependencies(
mCommandQueue,
- mOverviewProxyService,
+ mLauncherProxyService,
mNavBarHelper,
mNavigationModeController,
mSysUiState,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarButtonTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarButtonTest.java
index 00e79f5a3ac2..fd4bb4bb8a37 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarButtonTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarButtonTest.java
@@ -40,7 +40,7 @@ import com.android.systemui.SysuiTestableContext;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -80,7 +80,7 @@ public class NavigationBarButtonTest extends SysuiTestCase {
.thenReturn(mEdgeBackGestureHandler);
mDependency.injectMockDependency(AssistManager.class);
- mDependency.injectMockDependency(OverviewProxyService.class);
+ mDependency.injectMockDependency(LauncherProxyService.class);
mDependency.injectMockDependency(KeyguardStateController.class);
mDependency.injectMockDependency(NavigationBarController.class);
mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarInflaterViewTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarInflaterViewTest.java
index e58c8f281fc1..85c093c16d88 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarInflaterViewTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarInflaterViewTest.java
@@ -35,7 +35,7 @@ import com.android.systemui.assist.AssistManager;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.views.buttons.ButtonDispatcher;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import org.junit.After;
import org.junit.Before;
@@ -55,7 +55,7 @@ public class NavigationBarInflaterViewTest extends SysuiTestCase {
@Before
public void setUp() {
mDependency.injectMockDependency(AssistManager.class);
- mDependency.injectMockDependency(OverviewProxyService.class);
+ mDependency.injectMockDependency(LauncherProxyService.class);
mDependency.injectMockDependency(NavigationModeController.class);
mDependency.injectMockDependency(NavigationBarController.class);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
index 647603c418ee..09e49eb217b0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
@@ -16,9 +16,9 @@
package com.android.systemui.navigationbar.views;
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_VISIBLE;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
+import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING;
import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
import static android.inputmethodservice.InputMethodService.IME_VISIBLE;
@@ -31,9 +31,9 @@ import static com.android.systemui.assist.AssistManager.INVOCATION_TYPE_HOME_BUT
import static com.android.systemui.navigationbar.views.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
import static com.android.systemui.navigationbar.views.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_IME_SWITCHER_BUTTON_LONGPRESS;
import static com.android.systemui.navigationbar.views.buttons.KeyButtonView.NavBarButtonEvent.NAVBAR_IME_SWITCHER_BUTTON_TAP;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_ALT_BACK;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISMISS_IME;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.google.common.truth.Truth.assertThat;
@@ -106,7 +106,7 @@ import com.android.systemui.navigationbar.views.buttons.KeyButtonView;
import com.android.systemui.navigationbar.views.buttons.NavBarButtonClickLogger;
import com.android.systemui.navigationbar.views.buttons.NavbarOrientationTrackingLogger;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.FakeDisplayTracker;
@@ -185,7 +185,7 @@ public class NavigationBarTest extends SysuiTestCase {
@Mock
private SystemActions mSystemActions;
@Mock
- private OverviewProxyService mOverviewProxyService;
+ private LauncherProxyService mLauncherProxyService;
@Mock
private StatusBarStateController mStatusBarStateController;
@Mock
@@ -285,14 +285,14 @@ public class NavigationBarTest extends SysuiTestCase {
mDependency.injectMockDependency(KeyguardStateController.class);
mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
mDependency.injectMockDependency(NavigationBarController.class);
- mDependency.injectTestDependency(OverviewProxyService.class, mOverviewProxyService);
+ mDependency.injectTestDependency(LauncherProxyService.class, mLauncherProxyService);
mDependency.injectTestDependency(NavigationModeController.class, mNavigationModeController);
TestableLooper.get(this).runWithLooper(() -> {
mNavBarHelper = spy(new NavBarHelper(mContext, mock(AccessibilityManager.class),
mock(AccessibilityButtonModeObserver.class),
mock(AccessibilityButtonTargetsObserver.class),
mock(AccessibilityGestureTargetsObserver.class),
- mSystemActions, mOverviewProxyService,
+ mSystemActions, mLauncherProxyService,
() -> mock(AssistManager.class), () -> Optional.of(mCentralSurfaces),
mKeyguardStateController, mock(NavigationModeController.class),
mEdgeBackGestureHandlerFactory, mock(IWindowManager.class),
@@ -503,7 +503,7 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_VISIBLE), eq(true));
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE), eq(true));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_ALT_BACK), eq(true));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_BACK_DISMISS_IME), eq(true));
}
/**
@@ -518,7 +518,7 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_DEFAULT, false /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_VISIBLE), eq(true));
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE), eq(false));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_ALT_BACK), eq(true));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_BACK_DISMISS_IME), eq(true));
}
/**
@@ -536,7 +536,7 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_VISIBLE), eq(false));
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE), eq(false));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_ALT_BACK), eq(false));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_BACK_DISMISS_IME), eq(false));
}
/**
@@ -551,7 +551,7 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_ADJUST_NOTHING, true /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_VISIBLE), eq(true));
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE), eq(true));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_ALT_BACK), eq(false));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_BACK_DISMISS_IME), eq(false));
}
@Test
@@ -569,29 +569,27 @@ public class NavigationBarTest extends SysuiTestCase {
externalNavBar.init();
defaultNavBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
- BACK_DISPOSITION_DEFAULT, true);
+ BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
// Verify IME window state will be updated in default NavBar & external NavBar state reset.
- assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_VISIBLE
- | NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE,
- defaultNavBar.getNavigationIconHints());
- assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
- assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_VISIBLE) != 0);
- assertFalse((externalNavBar.getNavigationIconHints()
- & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0);
+ assertEquals(NAVBAR_BACK_DISMISS_IME | NAVBAR_IME_VISIBLE
+ | NAVBAR_IME_SWITCHER_BUTTON_VISIBLE,
+ defaultNavBar.getNavbarFlags());
+ assertFalse((externalNavBar.getNavbarFlags() & NAVBAR_BACK_DISMISS_IME) != 0);
+ assertFalse((externalNavBar.getNavbarFlags() & NAVBAR_IME_VISIBLE) != 0);
+ assertFalse((externalNavBar.getNavbarFlags() & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0);
externalNavBar.setImeWindowStatus(EXTERNAL_DISPLAY_ID, IME_VISIBLE,
- BACK_DISPOSITION_DEFAULT, true);
+ BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
defaultNavBar.setImeWindowStatus(DEFAULT_DISPLAY, 0 /* vis */,
- BACK_DISPOSITION_DEFAULT, false);
+ BACK_DISPOSITION_DEFAULT, false /* showImeSwitcher */);
// Verify IME window state will be updated in external NavBar & default NavBar state reset.
- assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_VISIBLE
- | NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE,
- externalNavBar.getNavigationIconHints());
- assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
- assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_VISIBLE) != 0);
- assertFalse((defaultNavBar.getNavigationIconHints()
- & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0);
+ assertEquals(NAVBAR_BACK_DISMISS_IME | NAVBAR_IME_VISIBLE
+ | NAVBAR_IME_SWITCHER_BUTTON_VISIBLE,
+ externalNavBar.getNavbarFlags());
+ assertFalse((defaultNavBar.getNavbarFlags() & NAVBAR_BACK_DISMISS_IME) != 0);
+ assertFalse((defaultNavBar.getNavbarFlags() & NAVBAR_IME_VISIBLE) != 0);
+ assertFalse((defaultNavBar.getNavbarFlags() & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0);
}
@Test
@@ -606,32 +604,29 @@ public class NavigationBarTest extends SysuiTestCase {
// Verify navbar altered back icon when an app is showing IME
mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
- BACK_DISPOSITION_DEFAULT, true);
- assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
- assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_VISIBLE) != 0);
- assertTrue((mNavigationBar.getNavigationIconHints()
- & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0);
+ BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
+ assertTrue((mNavigationBar.getNavbarFlags() & NAVBAR_BACK_DISMISS_IME) != 0);
+ assertTrue((mNavigationBar.getNavbarFlags() & NAVBAR_IME_VISIBLE) != 0);
+ assertTrue((mNavigationBar.getNavbarFlags() & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0);
// Verify navbar didn't alter and showing back icon when the keyguard is showing without
// requesting IME insets visible.
doReturn(true).when(mKeyguardStateController).isShowing();
mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
- BACK_DISPOSITION_DEFAULT, true);
- assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
- assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_VISIBLE) != 0);
- assertFalse((mNavigationBar.getNavigationIconHints()
- & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0);
+ BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
+ assertFalse((mNavigationBar.getNavbarFlags() & NAVBAR_BACK_DISMISS_IME) != 0);
+ assertFalse((mNavigationBar.getNavbarFlags() & NAVBAR_IME_VISIBLE) != 0);
+ assertFalse((mNavigationBar.getNavbarFlags() & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0);
// Verify navbar altered and showing back icon when the keyguard is showing and
// requesting IME insets visible.
windowInsets = new WindowInsets.Builder().setVisible(ime(), true).build();
doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets();
mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
- BACK_DISPOSITION_DEFAULT, true);
- assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
- assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_VISIBLE) != 0);
- assertTrue((mNavigationBar.getNavigationIconHints()
- & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0);
+ BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
+ assertTrue((mNavigationBar.getNavbarFlags() & NAVBAR_BACK_DISMISS_IME) != 0);
+ assertTrue((mNavigationBar.getNavbarFlags() & NAVBAR_IME_VISIBLE) != 0);
+ assertTrue((mNavigationBar.getNavbarFlags() & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0);
}
@Test
@@ -695,7 +690,7 @@ public class NavigationBarTest extends SysuiTestCase {
mock(AccessibilityManager.class),
deviceProvisionedController,
new MetricsLogger(),
- mOverviewProxyService,
+ mLauncherProxyService,
mNavigationModeController,
mStatusBarStateController,
mStatusBarKeyguardViewManager,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTransitionsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTransitionsTest.java
index 3621ab975daf..cff9beccc729 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTransitionsTest.java
@@ -36,7 +36,7 @@ import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationModeController;
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.LauncherProxyService;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.shared.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
@@ -72,7 +72,7 @@ public class NavigationBarTransitionsTest extends SysuiTestCase {
when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
.thenReturn(mEdgeBackGestureHandler);
mDependency.injectMockDependency(AssistManager.class);
- mDependency.injectMockDependency(OverviewProxyService.class);
+ mDependency.injectMockDependency(LauncherProxyService.class);
mDependency.injectMockDependency(StatusBarStateController.class);
mDependency.injectMockDependency(KeyguardStateController.class);
mDependency.injectMockDependency(NavigationBarController.class);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/buttons/KeyButtonViewTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/buttons/KeyButtonViewTest.java
index 403a883e1760..58ec0c7a0e72 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/buttons/KeyButtonViewTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/buttons/KeyButtonViewTest.java
@@ -51,7 +51,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import org.junit.Before;
import org.junit.Test;
@@ -76,7 +76,7 @@ public class KeyButtonViewTest extends SysuiTestCase {
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
- mDependency.injectMockDependency(OverviewProxyService.class);
+ mDependency.injectMockDependency(LauncherProxyService.class);
mDependency.injectMockDependency(AssistManager.class);
mUiEventLogger = mDependency.injectMockDependency(UiEventLogger.class);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModelTest.kt
index 855931c32671..52b9e47e6d3d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModelTest.kt
@@ -21,7 +21,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.Swipe
-import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.UserActionResult.HideOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay.HideCurrentOverlays
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
@@ -53,7 +55,7 @@ class NotificationsShadeOverlayActionsViewModelTest : SysuiTestCase() {
val actions by collectLastValue(underTest.actions)
underTest.activateIn(this)
- assertThat((actions?.get(Swipe.Up) as? UserActionResult.HideOverlay)?.overlay)
+ assertThat((actions?.get(Swipe.Up) as? HideOverlay)?.overlay)
.isEqualTo(Overlays.NotificationsShade)
assertThat(actions?.get(Swipe.Down)).isNull()
}
@@ -64,7 +66,7 @@ class NotificationsShadeOverlayActionsViewModelTest : SysuiTestCase() {
val actions by collectLastValue(underTest.actions)
underTest.activateIn(this)
- assertThat((actions?.get(Back) as? UserActionResult.HideOverlay)?.overlay)
+ assertThat((actions?.get(Back) as? HideOverlay)?.overlay)
.isEqualTo(Overlays.NotificationsShade)
}
@@ -74,11 +76,11 @@ class NotificationsShadeOverlayActionsViewModelTest : SysuiTestCase() {
val actions by collectLastValue(underTest.actions)
underTest.activateIn(this)
- assertThat(
- (actions?.get(Swipe.Down(fromSource = SceneContainerEdge.TopRight))
- as? UserActionResult.ReplaceByOverlay)
- ?.overlay
- )
- .isEqualTo(Overlays.QuickSettingsShade)
+ val action =
+ (actions?.get(Swipe.Down(fromSource = SceneContainerEdge.TopRight)) as? ShowOverlay)
+ assertThat(action?.overlay).isEqualTo(Overlays.QuickSettingsShade)
+ val overlaysToHide = action?.hideCurrentOverlays as? HideCurrentOverlays.Some
+ assertThat(overlaysToHide).isNotNull()
+ assertThat(overlaysToHide?.overlays).containsExactly(Overlays.NotificationsShade)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayContentViewModelTest.kt
index b30313e07012..675960832edc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayContentViewModelTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.notifications.ui.viewmodel
-import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -36,8 +35,8 @@ import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.ui.viewmodel.notificationsShadeOverlayContentViewModel
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
@@ -56,7 +55,6 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-@EnableFlags(DualShade.FLAG_NAME)
class NotificationsShadeOverlayContentViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
@@ -68,6 +66,7 @@ class NotificationsShadeOverlayContentViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
kosmos.sceneContainerStartable.start()
+ kosmos.enableDualShade()
underTest.activateIn(testScope)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index e9633f49f76d..ff005c2b767a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -16,7 +16,6 @@
package com.android.systemui.qs;
-import static com.android.systemui.Flags.FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS;
import static com.android.systemui.flags.SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag;
import static com.google.common.truth.Truth.assertThat;
@@ -41,8 +40,6 @@ import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.testing.TestableLooper.RunWithLooper;
import android.view.ContextThemeWrapper;
@@ -87,6 +84,7 @@ import javax.inject.Provider;
import kotlinx.coroutines.flow.MutableStateFlow;
import kotlinx.coroutines.flow.StateFlow;
+
import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;
@@ -505,7 +503,6 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
}
@Test
- @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
public void setTiles_longPressEffectEnabled_nonNullLongPressEffectsAreProvided() {
mLongPressEffectProvider.mEffectsProvided = 0;
when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
@@ -516,16 +513,6 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
}
@Test
- @DisableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS)
- public void setTiles_longPressEffectDisabled_noLongPressEffectsAreProvided() {
- mLongPressEffectProvider.mEffectsProvided = 0;
- when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
- mController.setTiles();
-
- assertThat(mLongPressEffectProvider.mEffectsProvided).isEqualTo(0);
- }
-
- @Test
public void setTiles_differentTiles_extraTileRemoved() {
when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
mController.setTiles();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
index f90e1e931099..f89d70baf67d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
@@ -36,6 +36,7 @@ import com.android.systemui.qs.footer.FooterActionsTestUtils
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.res.R
import com.android.systemui.security.data.model.SecurityModel
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.policy.FakeSecurityController
import com.android.systemui.statusbar.policy.FakeUserInfoController
import com.android.systemui.statusbar.policy.FakeUserInfoController.FakeInfo
@@ -45,6 +46,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.FakeGlobalSettings
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -57,6 +59,7 @@ import org.junit.runner.RunWith
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.`when` as whenever
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@@ -78,51 +81,45 @@ class FooterActionsViewModelTest : SysuiTestCase() {
@Test
fun settingsButton() = runTest {
- val underTest = utils.footerActionsViewModel(showPowerButton = false)
+ val underTest =
+ utils.footerActionsViewModel(showPowerButton = false, shadeMode = ShadeMode.Single)
val settings = underTest.settings
assertThat(settings.icon)
.isEqualTo(
Icon.Resource(
R.drawable.ic_settings,
- ContentDescription.Resource(R.string.accessibility_quick_settings_settings)
+ ContentDescription.Resource(R.string.accessibility_quick_settings_settings),
)
)
assertThat(settings.backgroundColor).isEqualTo(R.attr.shadeInactive)
assertThat(settings.iconTint)
- .isEqualTo(
- Utils.getColorAttrDefaultColor(
- themedContext,
- R.attr.onShadeInactiveVariant,
- )
- )
+ .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeInactiveVariant))
}
@Test
fun powerButton() = runTest {
// Without power button.
- val underTestWithoutPower = utils.footerActionsViewModel(showPowerButton = false)
- assertThat(underTestWithoutPower.power).isNull()
+ val underTestWithoutPower =
+ utils.footerActionsViewModel(showPowerButton = false, shadeMode = ShadeMode.Single)
+ val withoutPower by collectLastValue(underTestWithoutPower.power)
+ assertThat(withoutPower).isNull()
// With power button.
- val underTestWithPower = utils.footerActionsViewModel(showPowerButton = true)
- val power = underTestWithPower.power
+ val underTestWithPower =
+ utils.footerActionsViewModel(showPowerButton = true, shadeMode = ShadeMode.Single)
+ val power by collectLastValue(underTestWithPower.power)
assertThat(power).isNotNull()
- assertThat(power!!.icon)
+ assertThat(checkNotNull(power).icon)
.isEqualTo(
Icon.Resource(
android.R.drawable.ic_lock_power_off,
- ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu)
+ ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
)
)
- assertThat(power.backgroundColor).isEqualTo(R.attr.shadeActive)
- assertThat(power.iconTint)
- .isEqualTo(
- Utils.getColorAttrDefaultColor(
- themedContext,
- R.attr.onShadeActive,
- ),
- )
+ assertThat(checkNotNull(power).backgroundColor).isEqualTo(R.attr.shadeActive)
+ assertThat(checkNotNull(power).iconTint)
+ .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeActive))
}
@Test
@@ -130,7 +127,6 @@ class FooterActionsViewModelTest : SysuiTestCase() {
val picture: Drawable = mock()
val userInfoController = FakeUserInfoController(FakeInfo(picture = picture))
val settings = FakeGlobalSettings(testDispatcher)
- val userId = 42
val userSwitcherControllerWrapper =
MockUserSwitcherControllerWrapper(currentUserName = "foo")
@@ -144,6 +140,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
val underTest =
utils.footerActionsViewModel(
showPowerButton = false,
+ shadeMode = ShadeMode.Single,
footerActionsInteractor =
utils.footerActionsInteractor(
userSwitcherRepository =
@@ -152,8 +149,8 @@ class FooterActionsViewModelTest : SysuiTestCase() {
userManager = userManager,
userInfoController = userInfoController,
userSwitcherController = userSwitcherControllerWrapper.controller,
- ),
- )
+ )
+ ),
)
// Collect the user switcher into currentUserSwitcher.
@@ -213,13 +210,12 @@ class FooterActionsViewModelTest : SysuiTestCase() {
val underTest =
utils.footerActionsViewModel(
+ shadeMode = ShadeMode.Single,
footerActionsInteractor =
utils.footerActionsInteractor(
qsSecurityFooterUtils = qsSecurityFooterUtils,
securityRepository =
- utils.securityRepository(
- securityController = securityController,
- ),
+ utils.securityRepository(securityController = securityController),
),
)
@@ -261,10 +257,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
fun foregroundServices() = runTest {
val securityController = FakeSecurityController()
val fgsManagerController =
- FakeFgsManagerController(
- showFooterDot = false,
- numRunningPackages = 0,
- )
+ FakeFgsManagerController(showFooterDot = false, numRunningPackages = 0)
val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
// Mock QSSecurityFooter to map a SecurityModel into a SecurityButtonConfig using the
@@ -276,13 +269,11 @@ class FooterActionsViewModelTest : SysuiTestCase() {
val underTest =
utils.footerActionsViewModel(
+ shadeMode = ShadeMode.Single,
footerActionsInteractor =
utils.footerActionsInteractor(
qsSecurityFooterUtils = qsSecurityFooterUtils,
- securityRepository =
- utils.securityRepository(
- securityController,
- ),
+ securityRepository = utils.securityRepository(securityController),
foregroundServicesRepository =
utils.foregroundServicesRepository(fgsManagerController),
),
@@ -340,14 +331,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
// Return a fake broadcastFlow that emits 3 fake events when collected.
val broadcastFlow = flowOf(Unit, Unit, Unit)
- whenever(
- broadcastDispatcher.broadcastFlow(
- any(),
- nullable(),
- anyInt(),
- nullable(),
- )
- )
+ whenever(broadcastDispatcher.broadcastFlow(any(), nullable(), anyInt(), nullable()))
.thenAnswer { broadcastFlow }
// Increment nDialogRequests whenever a request to show the dialog is made by the
@@ -359,6 +343,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
val underTest =
utils.footerActionsViewModel(
+ shadeMode = ShadeMode.Single,
footerActionsInteractor =
utils.footerActionsInteractor(
qsSecurityFooterUtils = qsSecurityFooterUtils,
@@ -376,7 +361,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
@Test
fun alpha_inSplitShade_followsExpansion() {
- val underTest = utils.footerActionsViewModel()
+ val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Split)
underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = true)
assertThat(underTest.alpha.value).isEqualTo(0f)
@@ -396,7 +381,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
@Test
fun backgroundAlpha_inSplitShade_followsExpansion_with_0_15_delay() {
- val underTest = utils.footerActionsViewModel()
+ val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Split)
val floatTolerance = 0.01f
underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = true)
@@ -420,7 +405,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
@Test
fun alpha_inSingleShade_followsExpansion_with_0_9_delay() {
- val underTest = utils.footerActionsViewModel()
+ val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Single)
val floatTolerance = 0.01f
underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = false)
@@ -444,7 +429,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
@Test
fun backgroundAlpha_inSingleShade_always1() {
- val underTest = utils.footerActionsViewModel()
+ val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Single)
underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = false)
assertThat(underTest.backgroundAlpha.value).isEqualTo(1f)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorTest.kt
index b5915386b443..c775bfd75f6e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorTest.kt
@@ -16,8 +16,6 @@
package com.android.systemui.qs.panels.domain.interactor
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -26,8 +24,9 @@ import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
import com.android.systemui.qs.panels.shared.model.PaginatedGridLayoutType
-import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
@@ -40,29 +39,27 @@ class GridLayoutTypeInteractorTest : SysuiTestCase() {
val Kosmos.underTest by Kosmos.Fixture { kosmos.gridLayoutTypeInteractor }
- @DisableFlags(DualShade.FLAG_NAME)
@Test
fun noDualShade_gridAlwaysPaginated() =
kosmos.runTest {
val type by collectLastValue(underTest.layout)
- fakeShadeRepository.setShadeLayoutWide(false)
+ kosmos.enableSingleShade()
assertThat(type).isEqualTo(PaginatedGridLayoutType)
- fakeShadeRepository.setShadeLayoutWide(true)
+ kosmos.enableSplitShade()
assertThat(type).isEqualTo(PaginatedGridLayoutType)
}
- @EnableFlags(DualShade.FLAG_NAME)
@Test
fun dualShade_gridAlwaysInfinite() =
kosmos.runTest {
val type by collectLastValue(underTest.layout)
- fakeShadeRepository.setShadeLayoutWide(false)
+ kosmos.enableDualShade(wideLayout = false)
assertThat(type).isEqualTo(InfiniteGridLayoutType)
- fakeShadeRepository.setShadeLayoutWide(true)
+ kosmos.enableDualShade(wideLayout = true)
assertThat(type).isEqualTo(InfiniteGridLayoutType)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt
index 35f7504ead50..2e7aeb433e04 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractorTest.kt
@@ -17,8 +17,6 @@
package com.android.systemui.qs.panels.domain.interactor
import android.content.res.mainResources
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -29,8 +27,9 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.qs.panels.data.repository.QSColumnsRepository
import com.android.systemui.qs.panels.data.repository.qsColumnsRepository
import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
@@ -65,35 +64,36 @@ class QSColumnsInteractorTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun withSingleShade_returnsCorrectValue() =
with(kosmos) {
testScope.runTest {
val latest by collectLastValue(underTest.columns)
+ kosmos.enableSingleShade()
+
assertThat(latest).isEqualTo(1)
}
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun withDualShade_returnsCorrectValue() =
with(kosmos) {
testScope.runTest {
val latest by collectLastValue(underTest.columns)
+ kosmos.enableDualShade()
+
assertThat(latest).isEqualTo(2)
}
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun withSplitShade_returnsCorrectValue() =
with(kosmos) {
testScope.runTest {
val latest by collectLastValue(underTest.columns)
- fakeShadeRepository.setShadeLayoutWide(true)
+ kosmos.enableSplitShade()
assertThat(latest).isEqualTo(3)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/MediaInRowInLandscapeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/MediaInRowInLandscapeViewModelTest.kt
index 635badac04f5..e686d4dde2f1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/MediaInRowInLandscapeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/MediaInRowInLandscapeViewModelTest.kt
@@ -21,7 +21,6 @@ import android.content.res.mainResources
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
-import com.android.systemui.flags.setFlagValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QQS
@@ -30,8 +29,9 @@ import com.android.systemui.media.controls.ui.controller.MediaLocation
import com.android.systemui.media.controls.ui.controller.mediaHostStatesManager
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.qs.composefragment.dagger.usingMediaInComposeFragment
-import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -57,7 +57,11 @@ class MediaInRowInLandscapeViewModelTest(private val testData: TestData) : Sysui
@Before
fun setUp() {
- mSetFlagsRule.setFlagValue(DualShade.FLAG_NAME, testData.shadeMode == ShadeMode.Dual)
+ when (testData.shadeMode) {
+ ShadeMode.Single -> kosmos.enableSingleShade()
+ ShadeMode.Split -> kosmos.enableSplitShade()
+ ShadeMode.Dual -> kosmos.enableDualShade()
+ }
}
@Test
@@ -66,7 +70,6 @@ class MediaInRowInLandscapeViewModelTest(private val testData: TestData) : Sysui
testScope.runTest {
underTest.activateIn(testScope)
- shadeRepository.setShadeLayoutWide(testData.shadeMode != ShadeMode.Single)
val config =
Configuration(mainResources.configuration).apply {
orientation = testData.orientation
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QSColumnsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QSColumnsViewModelTest.kt
index 4ae8589de87b..241cdbfbef83 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QSColumnsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/QSColumnsViewModelTest.kt
@@ -17,8 +17,6 @@
package com.android.systemui.qs.panels.ui.viewmodel
import android.content.res.mainResources
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -37,7 +35,8 @@ import com.android.systemui.qs.composefragment.dagger.usingMediaInComposeFragmen
import com.android.systemui.qs.panels.data.repository.QSColumnsRepository
import com.android.systemui.qs.panels.data.repository.qsColumnsRepository
import com.android.systemui.res.R
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.disableDualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
@@ -66,12 +65,12 @@ class QSColumnsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun mediaLocationNull_singleOrSplit_alwaysSingleShadeColumns() =
with(kosmos) {
testScope.runTest {
val underTest = qsColumnsViewModelFactory.create(null)
underTest.activateIn(testScope)
+ kosmos.disableDualShade()
setConfigurationForMediaInRow(mediaInRow = false)
@@ -89,12 +88,12 @@ class QSColumnsViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun mediaLocationNull_dualShade_alwaysDualShadeColumns() =
with(kosmos) {
testScope.runTest {
val underTest = qsColumnsViewModelFactory.create(null)
underTest.activateIn(testScope)
+ kosmos.enableDualShade()
setConfigurationForMediaInRow(mediaInRow = false)
@@ -112,12 +111,12 @@ class QSColumnsViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun mediaLocationQS_dualShade_alwaysDualShadeColumns() =
with(kosmos) {
testScope.runTest {
val underTest = qsColumnsViewModelFactory.create(LOCATION_QS)
underTest.activateIn(testScope)
+ kosmos.enableDualShade()
setConfigurationForMediaInRow(mediaInRow = false)
@@ -134,12 +133,12 @@ class QSColumnsViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun mediaLocationQQS_dualShade_alwaysDualShadeColumns() =
with(kosmos) {
testScope.runTest {
val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
underTest.activateIn(testScope)
+ kosmos.enableDualShade()
setConfigurationForMediaInRow(mediaInRow = false)
@@ -156,12 +155,12 @@ class QSColumnsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun mediaLocationQS_singleOrSplit_halfColumnsOnCorrectConfigurationAndVisible() =
with(kosmos) {
testScope.runTest {
val underTest = qsColumnsViewModelFactory.create(LOCATION_QS)
underTest.activateIn(testScope)
+ kosmos.disableDualShade()
setConfigurationForMediaInRow(mediaInRow = false)
runCurrent()
@@ -181,12 +180,12 @@ class QSColumnsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun mediaLocationQQS_singleOrSplit_halfColumnsOnCorrectConfigurationAndVisible() =
with(kosmos) {
testScope.runTest {
val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
underTest.activateIn(testScope)
+ kosmos.disableDualShade()
setConfigurationForMediaInRow(mediaInRow = false)
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
index fecd8c3cacca..4c834b396df6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
@@ -37,6 +37,7 @@ import com.android.systemui.qs.QsEventLogger
import com.android.systemui.qs.flags.QSComposeFragment
import com.android.systemui.qs.flags.QsDetailedView
import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.qs.tiles.dialog.InternetDetailsViewModel
import com.android.systemui.qs.tiles.dialog.InternetDialogManager
import com.android.systemui.qs.tiles.dialog.WifiStateWorker
import com.android.systemui.res.R
@@ -109,6 +110,7 @@ class InternetTileNewImplTest(flags: FlagsParameterization) : SysuiTestCase() {
@Mock private lateinit var dialogManager: InternetDialogManager
@Mock private lateinit var wifiStateWorker: WifiStateWorker
@Mock private lateinit var accessPointController: AccessPointController
+ @Mock private lateinit var internetDetailsViewModelFactory: InternetDetailsViewModel.Factory
@Before
fun setUp() {
@@ -145,6 +147,7 @@ class InternetTileNewImplTest(flags: FlagsParameterization) : SysuiTestCase() {
dialogManager,
wifiStateWorker,
accessPointController,
+ internetDetailsViewModelFactory
)
underTest.initialize()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractorTest.kt
index a29289a7409a..b5aaadcb7e0c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractorTest.kt
@@ -40,6 +40,7 @@ import com.android.systemui.qs.tiles.impl.custom.customTileRepository
import com.android.systemui.qs.tiles.impl.custom.customTileServiceInteractor
import com.android.systemui.qs.tiles.impl.custom.customTileSpec
import com.android.systemui.qs.tiles.impl.custom.data.entity.CustomTileDefaults
+import com.android.systemui.qs.tiles.impl.custom.qsTileLogger
import com.android.systemui.testKosmos
import com.android.systemui.user.data.repository.fakeUserRepository
import com.android.systemui.user.data.repository.userRepository
@@ -72,6 +73,7 @@ class CustomTileDataInteractorTest : SysuiTestCase() {
packageUpdatesRepository = customTilePackagesUpdatesRepository,
userRepository = userRepository,
tileScope = testScope.backgroundScope,
+ qsTileLogger = kosmos.qsTileLogger,
)
}
@@ -152,7 +154,7 @@ class CustomTileDataInteractorTest : SysuiTestCase() {
collectLastValue(
underTest.tileData(
TEST_USER_1.userHandle,
- flowOf(DataUpdateTrigger.InitialRequest)
+ flowOf(DataUpdateTrigger.InitialRequest),
)
)
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt
index e4a988860a6e..ce4a3432a5b4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractorTest.kt
@@ -26,13 +26,13 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
+import com.android.systemui.qs.tiles.dialog.InternetDetailsContentManager
+import com.android.systemui.qs.tiles.dialog.InternetDetailsViewModel
import com.android.systemui.qs.tiles.dialog.InternetDialogManager
import com.android.systemui.qs.tiles.dialog.WifiStateWorker
import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel
import com.android.systemui.statusbar.connectivity.AccessPointController
-import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.nullable
-import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -40,9 +40,10 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mock
-import org.mockito.Mockito.verify
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@SmallTest
@@ -54,15 +55,27 @@ class InternetTileUserActionInteractorTest : SysuiTestCase() {
private lateinit var underTest: InternetTileUserActionInteractor
- @Mock private lateinit var internetDialogManager: InternetDialogManager
- @Mock private lateinit var wifiStateWorker: WifiStateWorker
- @Mock private lateinit var controller: AccessPointController
+ private lateinit var internetDialogManager: InternetDialogManager
+ private lateinit var wifiStateWorker: WifiStateWorker
+ private lateinit var controller: AccessPointController
+ private lateinit var internetDetailsViewModelFactory: InternetDetailsViewModel.Factory
+ private lateinit var internetDetailsContentManagerFactory: InternetDetailsContentManager.Factory
+ private lateinit var internetDetailsViewModel: InternetDetailsViewModel
@Before
fun setup() {
internetDialogManager = mock<InternetDialogManager>()
wifiStateWorker = mock<WifiStateWorker>()
controller = mock<AccessPointController>()
+ internetDetailsViewModelFactory = mock<InternetDetailsViewModel.Factory>()
+ internetDetailsContentManagerFactory = mock<InternetDetailsContentManager.Factory>()
+ internetDetailsViewModel =
+ InternetDetailsViewModel(
+ onLongClick = {},
+ accessPointController = mock<AccessPointController>(),
+ contentManagerFactory = internetDetailsContentManagerFactory,
+ )
+ whenever(internetDetailsViewModelFactory.create(any())).thenReturn(internetDetailsViewModel)
underTest =
InternetTileUserActionInteractor(
@@ -71,6 +84,7 @@ class InternetTileUserActionInteractorTest : SysuiTestCase() {
wifiStateWorker,
controller,
inputHandler,
+ internetDetailsViewModelFactory,
)
}
@@ -102,7 +116,7 @@ class InternetTileUserActionInteractorTest : SysuiTestCase() {
underTest.handleInput(QSTileInputTestKtx.longClick(input))
QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
- Truth.assertThat(it.intent.action).isEqualTo(Settings.ACTION_WIFI_SETTINGS)
+ assertThat(it.intent.action).isEqualTo(Settings.ACTION_WIFI_SETTINGS)
}
}
@@ -114,7 +128,7 @@ class InternetTileUserActionInteractorTest : SysuiTestCase() {
underTest.handleInput(QSTileInputTestKtx.longClick(input))
QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
- Truth.assertThat(it.intent.action).isEqualTo(Settings.ACTION_WIFI_SETTINGS)
+ assertThat(it.intent.action).isEqualTo(Settings.ACTION_WIFI_SETTINGS)
}
}
@@ -141,8 +155,7 @@ class InternetTileUserActionInteractorTest : SysuiTestCase() {
@Test
fun detailsViewModel() =
kosmos.testScope.runTest {
- assertThat(underTest.detailsViewModel.getTitle())
- .isEqualTo("Internet")
+ assertThat(underTest.detailsViewModel.getTitle()).isEqualTo("Internet")
assertThat(underTest.detailsViewModel.getSubTitle())
.isEqualTo("Tab a network to connect")
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt
index 424afe171f96..e2d33b6fd3cc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt
@@ -107,7 +107,6 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
@Test
fun addAndRemoveMedia_mediaVisibilityIsUpdated() =
testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
val isMediaVisible by collectLastValue(underTest.isMediaVisible)
val userMedia = MediaData(active = true)
@@ -125,7 +124,6 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
@Test
fun addInactiveMedia_mediaVisibilityIsUpdated() =
testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
val isMediaVisible by collectLastValue(underTest.isMediaVisible)
val userMedia = MediaData(active = false)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModelTest.kt
index 939644594d31..df2dd99c779e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModelTest.kt
@@ -21,7 +21,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.Swipe
-import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.UserActionResult.HideOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay.HideCurrentOverlays
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
@@ -53,7 +55,7 @@ class QuickSettingsShadeOverlayActionsViewModelTest : SysuiTestCase() {
val actions by collectLastValue(underTest.actions)
underTest.activateIn(this)
- assertThat((actions?.get(Swipe.Up) as? UserActionResult.HideOverlay)?.overlay)
+ assertThat((actions?.get(Swipe.Up) as? HideOverlay)?.overlay)
.isEqualTo(Overlays.QuickSettingsShade)
assertThat(actions?.get(Swipe.Down)).isNull()
}
@@ -66,7 +68,7 @@ class QuickSettingsShadeOverlayActionsViewModelTest : SysuiTestCase() {
underTest.activateIn(this)
assertThat(isEditing).isFalse()
- assertThat((actions?.get(Back) as? UserActionResult.HideOverlay)?.overlay)
+ assertThat((actions?.get(Back) as? HideOverlay)?.overlay)
.isEqualTo(Overlays.QuickSettingsShade)
}
@@ -87,11 +89,11 @@ class QuickSettingsShadeOverlayActionsViewModelTest : SysuiTestCase() {
val actions by collectLastValue(underTest.actions)
underTest.activateIn(this)
- assertThat(
- (actions?.get(Swipe.Down(fromSource = SceneContainerEdge.TopLeft))
- as? UserActionResult.ReplaceByOverlay)
- ?.overlay
- )
- .isEqualTo(Overlays.NotificationsShade)
+ val action =
+ (actions?.get(Swipe.Down(fromSource = SceneContainerEdge.TopLeft)) as? ShowOverlay)
+ assertThat(action?.overlay).isEqualTo(Overlays.NotificationsShade)
+ val overlaysToHide = action?.hideCurrentOverlays as? HideCurrentOverlays.Some
+ assertThat(overlaysToHide).isNotNull()
+ assertThat(overlaysToHide?.overlays).containsExactly(Overlays.QuickSettingsShade)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayContentViewModelTest.kt
index 7d366f65d64a..01714d7a4b87 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayContentViewModelTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.qs.ui.viewmodel
-import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -36,9 +35,8 @@ import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationScrollViewModel
@@ -57,7 +55,6 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-@EnableFlags(DualShade.FLAG_NAME)
class QuickSettingsShadeOverlayContentViewModelTest : SysuiTestCase() {
private val kosmos =
@@ -72,6 +69,7 @@ class QuickSettingsShadeOverlayContentViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
kosmos.sceneContainerStartable.start()
+ kosmos.enableDualShade()
underTest.activateIn(testScope)
}
@@ -131,7 +129,7 @@ class QuickSettingsShadeOverlayContentViewModelTest : SysuiTestCase() {
@Test
fun showHeader_showsOnNarrowScreen() =
testScope.runTest {
- kosmos.shadeRepository.setShadeLayoutWide(false)
+ kosmos.enableDualShade(wideLayout = false)
runCurrent()
assertThat(underTest.showHeader).isTrue()
@@ -140,7 +138,7 @@ class QuickSettingsShadeOverlayContentViewModelTest : SysuiTestCase() {
@Test
fun showHeader_hidesOnWideScreen() =
testScope.runTest {
- kosmos.shadeRepository.setShadeLayoutWide(true)
+ kosmos.enableDualShade(wideLayout = true)
runCurrent()
assertThat(underTest.showHeader).isFalse()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt
index 959081663b56..707cd0493e36 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractorTest.kt
@@ -18,8 +18,6 @@
package com.android.systemui.scene.domain.interactor
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
@@ -36,7 +34,8 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.sceneDataSource
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.disableDualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
@@ -72,9 +71,9 @@ class SceneContainerOcclusionInteractorTest : SysuiTestCase() {
private val underTest by lazy { kosmos.sceneContainerOcclusionInteractor }
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun invisibleDueToOcclusion_dualShadeDisabled() =
testScope.runTest {
+ kosmos.disableDualShade()
val invisibleDueToOcclusion by collectLastValue(underTest.invisibleDueToOcclusion)
val keyguardState by collectLastValue(keyguardTransitionInteractor.currentKeyguardState)
@@ -134,9 +133,9 @@ class SceneContainerOcclusionInteractorTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun invisibleDueToOcclusion_dualShadeEnabled() =
testScope.runTest {
+ kosmos.enableDualShade()
val invisibleDueToOcclusion by collectLastValue(underTest.invisibleDueToOcclusion)
val keyguardState by collectLastValue(keyguardTransitionInteractor.currentKeyguardState)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index cb7267b2c34c..ef70305a3f47 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -103,8 +103,9 @@ import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
+import com.android.systemui.shade.domain.interactor.disableDualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shared.system.QuickStepContract
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
@@ -187,9 +188,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun hydrateVisibility() =
testScope.runTest {
+ kosmos.disableDualShade()
val currentDesiredSceneKey by collectLastValue(sceneInteractor.currentScene)
val isVisible by collectLastValue(sceneInteractor.isVisible)
val transitionStateFlow =
@@ -248,9 +249,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun hydrateVisibility_dualShade() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentDesiredSceneKey by collectLastValue(sceneInteractor.currentScene)
val currentDesiredOverlays by collectLastValue(sceneInteractor.currentOverlays)
val isVisible by collectLastValue(sceneInteractor.isVisible)
@@ -1739,9 +1740,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun hydrateInteractionState_whileLocked() =
testScope.runTest {
+ kosmos.disableDualShade()
val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
underTest.start()
runCurrent()
@@ -1826,9 +1827,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun hydrateInteractionState_whileUnlocked() =
testScope.runTest {
+ kosmos.disableDualShade()
val transitionStateFlow =
prepareState(
authenticationMethod = AuthenticationMethodModel.Pin,
@@ -1915,9 +1916,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun hydrateInteractionState_dualShade_whileLocked() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentDesiredOverlays by collectLastValue(sceneInteractor.currentOverlays)
val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
underTest.start()
@@ -2004,9 +2005,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun hydrateInteractionState_dualShade_whileUnlocked() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentDesiredOverlays by collectLastValue(sceneInteractor.currentOverlays)
val transitionStateFlow =
prepareState(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index fc915ca24d89..048dd66ae1da 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -16,8 +16,6 @@
package com.android.systemui.scene.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -32,9 +30,10 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -53,7 +52,6 @@ class GoneUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val shadeRepository by lazy { kosmos.shadeRepository }
private lateinit var underTest: GoneUserActionsViewModel
@Before
@@ -63,44 +61,40 @@ class GoneUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun downTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
testScope.runTest {
val userActions by collectLastValue(underTest.actions)
- shadeRepository.setShadeLayoutWide(true)
+ kosmos.enableSplitShade()
runCurrent()
assertThat(userActions?.get(Swipe.Down)?.transitionKey).isEqualTo(ToSplitShade)
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun downTransitionKey_splitShadeDisabled_isNull() =
testScope.runTest {
val userActions by collectLastValue(underTest.actions)
- shadeRepository.setShadeLayoutWide(false)
+ kosmos.enableSingleShade()
runCurrent()
assertThat(userActions?.get(Swipe.Down)?.transitionKey).isNull()
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun downTransitionKey_dualShadeEnabled_isNull() =
testScope.runTest {
val userActions by collectLastValue(underTest.actions)
- shadeRepository.setShadeLayoutWide(true)
+ kosmos.enableDualShade(wideLayout = true)
runCurrent()
assertThat(userActions?.get(Swipe.Down)?.transitionKey).isNull()
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun swipeDownWithTwoFingers_singleShade_goesToQuickSettings() =
testScope.runTest {
val userActions by collectLastValue(underTest.actions)
- shadeRepository.setShadeLayoutWide(false)
+ kosmos.enableSingleShade()
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
@@ -108,11 +102,10 @@ class GoneUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun swipeDownWithTwoFingers_splitShade_goesToShade() =
testScope.runTest {
val userActions by collectLastValue(underTest.actions)
- shadeRepository.setShadeLayoutWide(true)
+ kosmos.enableSplitShade()
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
@@ -120,10 +113,10 @@ class GoneUserActionsViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun swipeDownWithTwoFingers_dualShadeEnabled_isNull() =
testScope.runTest {
val userActions by collectLastValue(underTest.actions)
+ kosmos.enableDualShade()
runCurrent()
assertThat(userActions?.get(swipeDownFromTopWithTwoFingers())).isNull()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index af895c82c975..399b48fb2fb9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -18,8 +18,6 @@
package com.android.systemui.scene.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.view.MotionEvent
import android.view.MotionEvent.ACTION_DOWN
import android.view.MotionEvent.ACTION_OUTSIDE
@@ -41,9 +39,10 @@ import com.android.systemui.scene.sceneContainerViewModelFactory
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
-import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.data.repository.fakeRemoteInputRepository
import com.android.systemui.testKosmos
@@ -69,7 +68,6 @@ class SceneContainerViewModelTest : SysuiTestCase() {
private val testScope by lazy { kosmos.testScope }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
- private val fakeShadeRepository by lazy { kosmos.fakeShadeRepository }
private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig }
private val fakeRemoteInputRepository by lazy { kosmos.fakeRemoteInputRepository }
private val falsingManager by lazy { kosmos.fakeFalsingManager }
@@ -324,44 +322,40 @@ class SceneContainerViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun edgeDetector_singleShade_usesDefaultEdgeDetector() =
testScope.runTest {
val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(false)
- assertThat(shadeMode).isEqualTo(ShadeMode.Single)
+ kosmos.enableSingleShade()
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun edgeDetector_splitShade_usesDefaultEdgeDetector() =
testScope.runTest {
val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(true)
- assertThat(shadeMode).isEqualTo(ShadeMode.Split)
+ kosmos.enableSplitShade()
+ assertThat(shadeMode).isEqualTo(ShadeMode.Split)
assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun edgeDetector_dualShade_narrowScreen_usesSplitEdgeDetector() =
testScope.runTest {
val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(false)
+ kosmos.enableDualShade(wideLayout = false)
assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun edgeDetector_dualShade_wideScreen_usesSplitEdgeDetector() =
testScope.runTest {
val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(true)
+ kosmos.enableDualShade(wideLayout = true)
assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 555c717e1e65..93d1f593e81f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -78,6 +78,7 @@ import java.util.Optional
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -220,6 +221,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
mock(),
{ configurationForwarder },
brightnessMirrorShowingInteractor,
+ UnconfinedTestDispatcher(),
)
controller.setupExpandedStatusBar()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
index b1ec740c5564..5c9cf82574a1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
@@ -16,8 +16,6 @@
package com.android.systemui.shade.domain.interactor
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
@@ -34,7 +32,7 @@ import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.shadeTestUtil
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -596,11 +594,13 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun expandNotificationsShade_dualShade_opensOverlay() =
testScope.runTest {
+ kosmos.enableDualShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).isEmpty()
@@ -611,12 +611,13 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun expandNotificationsShade_singleShade_switchesToShadeScene() =
testScope.runTest {
- shadeTestUtil.setSplitShade(false)
+ kosmos.enableSingleShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).isEmpty()
@@ -627,11 +628,14 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun expandNotificationsShade_dualShadeQuickSettingsOpen_replacesOverlay() =
testScope.runTest {
+ kosmos.enableDualShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+
underTest.expandQuickSettingsShade("reason")
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).containsExactly(Overlays.QuickSettingsShade)
@@ -642,11 +646,13 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun expandQuickSettingsShade_dualShade_opensOverlay() =
testScope.runTest {
+ kosmos.enableDualShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).isEmpty()
@@ -657,12 +663,13 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun expandQuickSettingsShade_singleShade_switchesToQuickSettingsScene() =
testScope.runTest {
- shadeTestUtil.setSplitShade(false)
+ kosmos.enableSingleShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).isEmpty()
@@ -673,12 +680,13 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun expandQuickSettingsShade_splitShade_switchesToShadeScene() =
testScope.runTest {
- shadeTestUtil.setSplitShade(true)
+ kosmos.enableSplitShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Split)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).isEmpty()
@@ -689,11 +697,14 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun expandQuickSettingsShade_dualShadeNotificationsOpen_replacesOverlay() =
testScope.runTest {
+ kosmos.enableDualShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+
underTest.expandNotificationsShade("reason")
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).containsExactly(Overlays.NotificationsShade)
@@ -704,9 +715,9 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun collapseNotificationsShade_dualShade_hidesOverlay() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
openShade(Overlays.NotificationsShade)
@@ -718,26 +729,27 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun collapseNotificationsShade_singleShade_switchesToLockscreen() =
testScope.runTest {
- shadeTestUtil.setSplitShade(false)
+ kosmos.enableSingleShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
+
sceneInteractor.changeScene(Scenes.Shade, "reason")
assertThat(currentScene).isEqualTo(Scenes.Shade)
assertThat(currentOverlays).isEmpty()
underTest.collapseNotificationsShade("reason")
-
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
assertThat(currentOverlays).isEmpty()
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun collapseQuickSettingsShade_dualShade_hidesOverlay() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
openShade(Overlays.QuickSettingsShade)
@@ -749,12 +761,14 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun collapseQuickSettingsShadeNotBypassingShade_singleShade_switchesToShade() =
testScope.runTest {
- shadeTestUtil.setSplitShade(false)
+ kosmos.enableSingleShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
+
sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
assertThat(currentOverlays).isEmpty()
@@ -769,12 +783,14 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun collapseQuickSettingsShadeNotBypassingShade_splitShade_switchesToLockscreen() =
testScope.runTest {
- shadeTestUtil.setSplitShade(true)
+ kosmos.enableSplitShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Split)
+
sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
assertThat(currentOverlays).isEmpty()
@@ -789,12 +805,14 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun collapseQuickSettingsShadeBypassingShade_singleShade_switchesToLockscreen() =
testScope.runTest {
- shadeTestUtil.setSplitShade(false)
+ kosmos.enableSingleShade()
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
+
sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
assertThat(currentOverlays).isEmpty()
@@ -809,9 +827,9 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun collapseEitherShade_dualShade_hidesBothOverlays() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
openShade(Overlays.QuickSettingsShade)
@@ -826,10 +844,13 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() {
}
private fun TestScope.openShade(overlay: OverlayKey) {
+ val shadeMode by collectLastValue(kosmos.shadeModeInteractor.shadeMode)
val isAnyExpanded by collectLastValue(underTest.isAnyExpanded)
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
val initialScene = checkNotNull(currentScene)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+
sceneInteractor.showOverlay(overlay, "reason")
kosmos.setSceneTransition(
ObservableTransitionState.Idle(initialScene, checkNotNull(currentOverlays))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
index d37e0fb2f047..0406c3e69b54 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
@@ -16,8 +16,6 @@
package com.android.systemui.shade.domain.startable
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
@@ -39,8 +37,9 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionListener
+import com.android.systemui.shade.domain.interactor.disableDualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.notificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.scrimController
@@ -88,10 +87,10 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun hydrateShadeMode_dualShadeDisabled() =
testScope.runTest {
overrideResource(R.bool.config_use_split_notification_shade, false)
+ kosmos.disableDualShade()
val shadeMode by collectLastValue(shadeInteractor.shadeMode)
underTest.start()
@@ -107,10 +106,10 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun hydrateShadeMode_dualShadeEnabled() =
testScope.runTest {
overrideResource(R.bool.config_use_split_notification_shade, false)
+ kosmos.enableDualShade()
val shadeMode by collectLastValue(shadeInteractor.shadeMode)
underTest.start()
@@ -159,11 +158,7 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {
assertThat(latestChangeEvent)
.isEqualTo(
- ShadeExpansionChangeEvent(
- fraction = 0f,
- expanded = false,
- tracking = false,
- )
+ ShadeExpansionChangeEvent(fraction = 0f, expanded = false, tracking = false)
)
changeScene(Scenes.Shade, transitionState) { progress ->
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
index 0da1e7f11582..8ce20d2a05e9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
@@ -1,8 +1,6 @@
package com.android.systemui.shade.ui.viewmodel
import android.content.Intent
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.provider.AlarmClock
import android.provider.Settings
import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
@@ -23,7 +21,8 @@ import com.android.systemui.plugins.activityStarter
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.disableDualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
import com.android.systemui.testKosmos
@@ -101,9 +100,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun onSystemIconChipClicked_locked_collapsesShadeToLockscreen() =
testScope.runTest {
+ kosmos.disableDualShade()
setDeviceEntered(false)
setScene(Scenes.Shade)
@@ -114,9 +113,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onSystemIconChipClicked_lockedOnQsShade_collapsesShadeToLockscreen() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(false)
@@ -132,9 +131,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onSystemIconChipClicked_lockedOnNotifShade_expandsQsShade() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(false)
@@ -151,9 +150,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(DualShade.FLAG_NAME)
fun onSystemIconChipClicked_unlocked_collapsesShadeToGone() =
testScope.runTest {
+ kosmos.disableDualShade()
setDeviceEntered(true)
setScene(Scenes.Shade)
@@ -164,9 +163,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onSystemIconChipClicked_unlockedOnQsShade_collapsesShadeToGone() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(true)
@@ -182,9 +181,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onSystemIconChipClicked_unlockedOnNotifShade_expandsQsShade() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(true)
@@ -201,9 +200,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onNotificationIconChipClicked_lockedOnNotifShade_collapsesShadeToLockscreen() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(false)
@@ -219,9 +218,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onNotificationIconChipClicked_lockedOnQsShade_expandsNotifShade() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(false)
@@ -238,9 +237,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onNotificationIconChipClicked_unlockedOnNotifShade_collapsesShadeToGone() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(true)
@@ -256,9 +255,9 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DualShade.FLAG_NAME)
fun onNotificationIconChipClicked_unlockedOnQsShade_expandsNotifShade() =
testScope.runTest {
+ kosmos.enableDualShade()
val currentScene by collectLastValue(sceneInteractor.currentScene)
val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
setDeviceEntered(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModelTest.kt
index a9d5790d1f08..27faeb8574a8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModelTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.shade.ui.viewmodel
import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
-import android.platform.test.annotations.DisableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -36,12 +35,11 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.shared.model.MediaData
-import com.android.systemui.qs.ui.adapter.fakeQSSceneAdapter
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.disableDualShade
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
import com.android.systemui.testKosmos
@@ -64,20 +62,19 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-@DisableFlags(DualShade.FLAG_NAME)
class ShadeSceneContentViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val shadeRepository by lazy { kosmos.shadeRepository }
- private val qsSceneAdapter by lazy { kosmos.fakeQSSceneAdapter }
private val underTest: ShadeSceneContentViewModel by lazy { kosmos.shadeSceneContentViewModel }
@Before
fun setUp() {
underTest.activateIn(testScope)
+ kosmos.disableDualShade()
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
index bbfc66a8d8e5..8f904f7fe132 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.shade.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -39,16 +38,16 @@ import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticati
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.qs.ui.adapter.fakeQSSceneAdapter
-import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.domain.interactor.disableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.startable.shadeStartable
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
@@ -66,13 +65,11 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-@DisableFlags(DualShade.FLAG_NAME)
class ShadeUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val sceneInteractor by lazy { kosmos.sceneInteractor }
- private val shadeRepository by lazy { kosmos.shadeRepository }
private val qsSceneAdapter by lazy { kosmos.fakeQSSceneAdapter }
private val underTest: ShadeUserActionsViewModel by lazy { kosmos.shadeUserActionsViewModel }
@@ -80,6 +77,7 @@ class ShadeUserActionsViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
kosmos.sceneContainerStartable.start()
+ kosmos.disableDualShade()
underTest.activateIn(testScope)
}
@@ -164,7 +162,7 @@ class ShadeUserActionsViewModelTest : SysuiTestCase() {
fun upTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
testScope.runTest {
val actions by collectLastValue(underTest.actions)
- shadeRepository.setShadeLayoutWide(true)
+ kosmos.enableSplitShade()
runCurrent()
assertThat(actions?.get(Swipe.Up)?.transitionKey).isEqualTo(ToSplitShade)
@@ -174,7 +172,7 @@ class ShadeUserActionsViewModelTest : SysuiTestCase() {
fun upTransitionKey_splitShadeDisable_isNull() =
testScope.runTest {
val actions by collectLastValue(underTest.actions)
- shadeRepository.setShadeLayoutWide(false)
+ kosmos.enableSingleShade()
runCurrent()
assertThat(actions?.get(Swipe.Up)?.transitionKey).isNull()
@@ -183,7 +181,7 @@ class ShadeUserActionsViewModelTest : SysuiTestCase() {
@Test
fun downTransitionSceneKey_inSplitShade_null() =
testScope.runTest {
- overrideResource(R.bool.config_use_split_notification_shade, true)
+ kosmos.enableSplitShade()
kosmos.shadeStartable.start()
val actions by collectLastValue(underTest.actions)
assertThat((actions?.get(Swipe.Down) as? UserActionResult.ChangeScene)?.toScene)
@@ -193,7 +191,7 @@ class ShadeUserActionsViewModelTest : SysuiTestCase() {
@Test
fun downTransitionSceneKey_notSplitShade_quickSettings() =
testScope.runTest {
- overrideResource(R.bool.config_use_split_notification_shade, false)
+ kosmos.enableSingleShade()
kosmos.shadeStartable.start()
val actions by collectLastValue(underTest.actions)
assertThat((actions?.get(Swipe.Down) as? UserActionResult.ChangeScene)?.toScene)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 0713a247a4a3..baaf6c9a76ae 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -84,7 +84,7 @@ import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.log.LogWtfHandlerRule;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.NotificationStateChangedListener;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -156,7 +156,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Mock
private NotificationClickNotifier mClickNotifier;
@Mock
- private OverviewProxyService mOverviewProxyService;
+ private LauncherProxyService mLauncherProxyService;
@Mock
private KeyguardManager mKeyguardManager;
@Mock
@@ -1142,7 +1142,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
(() -> mVisibilityProvider),
(() -> mNotifCollection),
mClickNotifier,
- (() -> mOverviewProxyService),
+ (() -> mLauncherProxyService),
NotificationLockscreenUserManagerTest.this.mKeyguardManager,
mStatusBarStateController,
mMainExecutor,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
index f8720b4fe5f8..a51e0c0add37 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -19,8 +19,6 @@
package com.android.systemui.statusbar
import android.animation.ObjectAnimator
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
@@ -53,8 +51,9 @@ import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInter
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.domain.interactor.disableDualShade
+import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
import com.android.systemui.testKosmos
import com.android.systemui.util.kotlin.JavaAdapter
@@ -246,9 +245,9 @@ class StatusBarStateControllerImplTest(flags: FlagsParameterization) : SysuiTest
@Test
@EnableSceneContainer
- @DisableFlags(DualShade.FLAG_NAME)
fun start_hydratesStatusBarState_whileLocked() =
testScope.runTest {
+ kosmos.disableDualShade()
var statusBarState = underTest.state
val listener =
object : StatusBarStateController.StateListener {
@@ -303,9 +302,9 @@ class StatusBarStateControllerImplTest(flags: FlagsParameterization) : SysuiTest
@Test
@EnableSceneContainer
- @DisableFlags(DualShade.FLAG_NAME)
fun start_hydratesStatusBarState_withAlternateBouncer() =
testScope.runTest {
+ kosmos.disableDualShade()
var statusBarState = underTest.state
val listener =
object : StatusBarStateController.StateListener {
@@ -349,9 +348,9 @@ class StatusBarStateControllerImplTest(flags: FlagsParameterization) : SysuiTest
@Test
@EnableSceneContainer
- @EnableFlags(DualShade.FLAG_NAME)
fun start_hydratesStatusBarState_dualShade_whileLocked() =
testScope.runTest {
+ kosmos.enableDualShade()
var statusBarState = underTest.state
val listener =
object : StatusBarStateController.StateListener {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 55f3717535b7..942e6554e5d9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifCh
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
+import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.UnconfinedFakeHeadsUpRowRepository
@@ -44,6 +45,7 @@ import com.android.systemui.statusbar.notification.headsup.PinnedStatus
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
@@ -629,22 +631,26 @@ class NotifChipsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
- fun chips_clickingChipNotifiesInteractor() =
+ @DisableFlags(
+ FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY,
+ StatusBarRootModernization.FLAG_NAME,
+ StatusBarChipsModernization.FLAG_NAME,
+ )
+ fun chips_chipsModernizationDisabled_clickingChipNotifiesInteractor() =
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
- val latestChipTap by
+ val latestChipTapKey by
collectLastValue(
kosmos.statusBarNotificationChipsInteractor.promotedNotificationChipTapEvent
)
+ val key = "clickTest"
setNotifs(
listOf(
activeNotificationModel(
- key = "clickTest",
+ key,
statusBarChipIcon = createStatusBarIconViewOrNull(),
- promotedContent =
- PromotedNotificationContentModel.Builder("clickTest").build(),
+ promotedContent = PromotedNotificationContentModel.Builder(key).build(),
)
)
)
@@ -652,7 +658,41 @@ class NotifChipsViewModelTest : SysuiTestCase() {
chip.onClickListenerLegacy!!.onClick(mock<View>())
- assertThat(latestChipTap).isEqualTo("clickTest")
+ assertThat(latestChipTapKey).isEqualTo(key)
+ }
+
+ @Test
+ @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
+ @EnableFlags(StatusBarRootModernization.FLAG_NAME, StatusBarChipsModernization.FLAG_NAME)
+ fun chips_chipsModernizationEnabled_clickingChipNotifiesInteractor() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.chips)
+ val latestChipTapKey by
+ collectLastValue(
+ kosmos.statusBarNotificationChipsInteractor.promotedNotificationChipTapEvent
+ )
+ val key = "clickTest"
+
+ setNotifs(
+ listOf(
+ activeNotificationModel(
+ key,
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
+ promotedContent = PromotedNotificationContentModel.Builder(key).build(),
+ )
+ )
+ )
+ val chip = latest!![0]
+
+ assertThat(chip.clickBehavior)
+ .isInstanceOf(
+ OngoingActivityChipModel.ClickBehavior.ShowHeadsUpNotification::class.java
+ )
+
+ (chip.clickBehavior as OngoingActivityChipModel.ClickBehavior.ShowHeadsUpNotification)
+ .onClick()
+
+ assertThat(latestChipTapKey).isEqualTo(key)
}
private fun setNotifs(notifs: List<ActiveNotificationModel>) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
index 3c772fdbe0b2..356eedbc9a45 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
@@ -29,6 +29,7 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE
import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_PUBLIC
+import com.android.systemui.statusbar.RankingBuilder
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
@@ -242,4 +243,42 @@ class NotifUiAdjustmentProviderTest : SysuiTestCase() {
// Then: need no re-inflation
assertFalse(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
}
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_NM_SUMMARIZATION_UI)
+ fun changeIsSummarization_needReInflation_newlySummarized() {
+ // Given: an Entry with no summarization
+ val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertThat(oldAdjustment.summarization).isNull()
+
+ // When: the Entry now has a summarization
+ val rb = RankingBuilder(entry.ranking)
+ rb.setSummarization("summary!")
+ entry.ranking = rb.build()
+ val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertThat(newAdjustment).isNotEqualTo(oldAdjustment)
+
+ // Then: Need re-inflation
+ assertTrue(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_NM_SUMMARIZATION_UI)
+ fun changeIsSummarization_needReInflation_summarizationChanged() {
+ // Given: an Entry with no summarization
+ val rb = RankingBuilder(entry.ranking)
+ rb.setSummarization("summary!")
+ entry.ranking = rb.build()
+ val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
+
+ // When: the Entry now has a new summarization
+ val rb2 = RankingBuilder(entry.ranking)
+ rb2.setSummarization("summary new!")
+ entry.ranking = rb2.build()
+ val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertThat(newAdjustment).isNotEqualTo(oldAdjustment)
+
+ // Then: Need re-inflation
+ assertTrue(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
index 9a42f5b02395..163ae47ad78a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel
import android.app.Flags
import android.app.NotificationManager.Policy
+import android.content.res.Configuration
+import android.os.LocaleList
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
@@ -27,6 +29,7 @@ import androidx.test.filters.SmallTest
import com.android.settingslib.notification.data.repository.updateNotificationPolicy
import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.kosmos.testScope
@@ -36,9 +39,12 @@ import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyS
import com.android.systemui.statusbar.policy.data.repository.zenModeRepository
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
+import java.util.Locale
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
@@ -53,6 +59,10 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
private val zenModeRepository = kosmos.zenModeRepository
private val activeNotificationListRepository = kosmos.activeNotificationListRepository
private val fakeSecureSettingsRepository = kosmos.fakeSecureSettingsRepository
+ private val fakeConfigurationRepository = kosmos.fakeConfigurationRepository
+
+ /** Backup of the current locales, to be restored at the end of the test if they are changed. */
+ private lateinit var originalLocales: LocaleList
private val underTest by lazy { kosmos.emptyShadeViewModel }
@@ -68,6 +78,18 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
mSetFlagsRule.setFlagsParameterization(flags)
}
+ @Before
+ fun setUp() {
+ originalLocales = context.resources.configuration.locales
+ updateLocales(LocaleList(Locale.US))
+ }
+
+ @After
+ fun tearDown() {
+ // Make sure we restore the original locale even if a test fails after changing it
+ updateLocales(originalLocales)
+ }
+
@Test
fun areNotificationsHiddenInShade_true() =
testScope.runTest {
@@ -144,6 +166,29 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
@EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API)
+ fun text_changesWhenLocaleChanges() =
+ testScope.runTest {
+ val text by collectLastValue(underTest.text)
+
+ zenModeRepository.updateNotificationPolicy(
+ suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
+ )
+ zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF)
+ runCurrent()
+
+ assertThat(text).isEqualTo("No notifications")
+
+ updateLocales(LocaleList(Locale.GERMAN))
+ runCurrent()
+
+ assertThat(text).isEqualTo("Keine Benachrichtigungen")
+
+ // Make sure we restore the original locales
+ updateLocales(originalLocales)
+ }
+
+ @Test
+ @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API)
fun text_reflectsModesHidingNotifications() =
testScope.runTest {
val text by collectLastValue(underTest.text)
@@ -285,4 +330,11 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
assertThat(onClick?.targetIntent?.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
assertThat(onClick?.backStack).isEmpty()
}
+
+ private fun updateLocales(locales: LocaleList) {
+ val configuration = Configuration()
+ configuration.setLocales(locales)
+ context.resources.updateConfiguration(configuration, context.resources.displayMetrics)
+ fakeConfigurationRepository.onConfigurationChange(configuration)
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
index 8d90d38a9eca..abb1edf8cb27 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
@@ -173,6 +173,17 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
@Test
@EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+ fun extractsContent_fromBaseStyle() {
+ val entry = createEntry { setStyle(null) }
+
+ val content = extractContent(entry)
+
+ assertThat(content).isNotNull()
+ assertThat(content?.style).isEqualTo(Style.Base)
+ }
+
+ @Test
+ @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
fun extractsContent_fromBigPictureStyle() {
val entry = createEntry { setStyle(BigPictureStyle()) }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt
new file mode 100644
index 000000000000..8163a68bc76f
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.stack
+
+import android.os.testableLooper
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.NotificationTestHelper
+import com.android.systemui.statusbar.notification.stack.MagneticNotificationRowManagerImpl.State
+import com.android.systemui.testKosmos
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@RunWithLooper
+class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
+
+ private val featureFlags = FakeFeatureFlagsClassic()
+ private val kosmos = testKosmos()
+ private val childrenNumber = 5
+ private val stackScrollLayout = mock<NotificationStackScrollLayout>()
+ private val sectionsManager = mock<NotificationSectionsManager>()
+ private val swipedMultiplier = 0.5f
+ private val msdlPlayer = kosmos.fakeMSDLPlayer
+
+ private val underTest = kosmos.magneticNotificationRowManagerImpl
+
+ private lateinit var notificationTestHelper: NotificationTestHelper
+ private lateinit var children: NotificationChildrenContainer
+
+ @Before
+ fun setUp() {
+ allowTestableLooperAsMainThread()
+ notificationTestHelper =
+ NotificationTestHelper(mContext, mDependency, kosmos.testableLooper, featureFlags)
+ children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
+ }
+
+ @Test
+ fun setMagneticAndRoundableTargets_onIdle_targetsGetSet() =
+ kosmos.testScope.runTest {
+ // WHEN the targets are set for a row
+ val row = children.attachedChildren[childrenNumber / 2]
+ setTargetsForRow(row)
+
+ // THEN the magnetic and roundable targets are defined and the state is TARGETS_SET
+ assertThat(underTest.currentState).isEqualTo(State.TARGETS_SET)
+ assertThat(underTest.currentMagneticListeners.isNotEmpty()).isTrue()
+ assertThat(underTest.currentRoundableTargets).isNotNull()
+ }
+
+ @Test
+ fun setMagneticRowTranslation_whenTargetsAreSet_startsPulling() =
+ kosmos.testScope.runTest {
+ // GIVEN targets are set
+ val row = children.attachedChildren[childrenNumber / 2]
+ setTargetsForRow(row)
+
+ // WHEN setting a translation for the swiped row
+ underTest.setMagneticRowTranslation(row, translation = 100f)
+
+ // THEN the state moves to PULLING
+ assertThat(underTest.currentState).isEqualTo(State.PULLING)
+ }
+
+ @Test
+ fun setMagneticRowTranslation_whenRowIsNotSwiped_doesNotSetMagneticTranslation() =
+ kosmos.testScope.runTest {
+ // GIVEN that targets are set
+ val row = children.attachedChildren[childrenNumber / 2]
+ setTargetsForRow(row)
+
+ // WHEN setting a translation for a row that is not being swiped
+ val differentRow = children.attachedChildren[childrenNumber / 2 - 1]
+ val canSetMagneticTranslation =
+ underTest.setMagneticRowTranslation(differentRow, translation = 100f)
+
+ // THEN no magnetic translations are set
+ assertThat(canSetMagneticTranslation).isFalse()
+ }
+
+ @Test
+ fun setMagneticRowTranslation_belowThreshold_whilePulling_setsMagneticTranslations() =
+ kosmos.testScope.runTest {
+ // GIVEN a threshold of 100 px
+ val threshold = 100f
+ underTest.setSwipeThresholdPx(threshold)
+
+ // GIVEN that targets are set and the rows are being pulled
+ val row = children.attachedChildren[childrenNumber / 2]
+ setTargetsForRow(row)
+ underTest.setMagneticRowTranslation(row, translation = 100f)
+
+ // WHEN setting a translation that will fall below the threshold
+ val translation = threshold / swipedMultiplier - 50f
+ underTest.setMagneticRowTranslation(row, translation)
+
+ // THEN the targets continue to be pulled and translations are set
+ assertThat(underTest.currentState).isEqualTo(State.PULLING)
+ assertThat(row.translation).isEqualTo(swipedMultiplier * translation)
+ }
+
+ @Test
+ fun setMagneticRowTranslation_aboveThreshold_whilePulling_detachesMagneticTargets() =
+ kosmos.testScope.runTest {
+ // GIVEN a threshold of 100 px
+ val threshold = 100f
+ underTest.setSwipeThresholdPx(threshold)
+
+ // GIVEN that targets are set and the rows are being pulled
+ val row = children.attachedChildren[childrenNumber / 2]
+ setTargetsForRow(row)
+ underTest.setMagneticRowTranslation(row, translation = 100f)
+
+ // WHEN setting a translation that will fall above the threshold
+ val translation = threshold / swipedMultiplier + 50f
+ underTest.setMagneticRowTranslation(row, translation)
+
+ // THEN the swiped view detaches and the correct detach haptics play
+ assertThat(underTest.currentState).isEqualTo(State.DETACHED)
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.SWIPE_THRESHOLD_INDICATOR)
+ }
+
+ @Test
+ fun setMagneticRowTranslation_whileDetached_setsTranslationAndStaysDetached() =
+ kosmos.testScope.runTest {
+ // GIVEN that the swiped view has been detached
+ val row = children.attachedChildren[childrenNumber / 2]
+ setDetachedState(row)
+
+ // WHEN setting a new translation
+ val translation = 300f
+ underTest.setMagneticRowTranslation(row, translation)
+
+ // THEN the swiped view continues to be detached
+ assertThat(underTest.currentState).isEqualTo(State.DETACHED)
+ }
+
+ @Test
+ fun onMagneticInteractionEnd_whilePulling_goesToIdle() =
+ kosmos.testScope.runTest {
+ // GIVEN targets are set
+ val row = children.attachedChildren[childrenNumber / 2]
+ setTargetsForRow(row)
+
+ // WHEN setting a translation for the swiped row
+ underTest.setMagneticRowTranslation(row, translation = 100f)
+
+ // WHEN the interaction ends on the row
+ underTest.onMagneticInteractionEnd(row, velocity = null)
+
+ // THEN the state resets
+ assertThat(underTest.currentState).isEqualTo(State.IDLE)
+ }
+
+ @Test
+ fun onMagneticInteractionEnd_whileDetached_goesToIdle() =
+ kosmos.testScope.runTest {
+ // GIVEN the swiped row is detached
+ val row = children.attachedChildren[childrenNumber / 2]
+ setDetachedState(row)
+
+ // WHEN the interaction ends on the row
+ underTest.onMagneticInteractionEnd(row, velocity = null)
+
+ // THEN the state resets
+ assertThat(underTest.currentState).isEqualTo(State.IDLE)
+ }
+
+ private fun setDetachedState(row: ExpandableNotificationRow) {
+ val threshold = 100f
+ underTest.setSwipeThresholdPx(threshold)
+
+ // Set the pulling state
+ setTargetsForRow(row)
+ underTest.setMagneticRowTranslation(row, translation = 100f)
+
+ // Set a translation that will fall above the threshold
+ val translation = threshold / swipedMultiplier + 50f
+ underTest.setMagneticRowTranslation(row, translation)
+
+ assertThat(underTest.currentState).isEqualTo(State.DETACHED)
+ }
+
+ private fun setTargetsForRow(row: ExpandableNotificationRow) {
+ underTest.setMagneticAndRoundableTargets(row, stackScrollLayout, sectionsManager)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 20cd6c7517e2..4ce13804c913 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -165,6 +165,8 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
@Mock
private SensitiveNotificationProtectionController mSensitiveNotificationProtectionController;
@Mock private ExpandHelper mExpandHelper;
+ @Mock private MagneticNotificationRowManager mMagneticNotificationRowManager;
+ @Mock private NotificationSectionsManager mSectionsManager;
@Captor
private ArgumentCaptor<Runnable> mSensitiveStateListenerArgumentCaptor;
@@ -798,7 +800,9 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
mActivityStarter,
new ResourcesSplitShadeStateController(),
mSensitiveNotificationProtectionController,
- mWallpaperInteractor);
+ mWallpaperInteractor,
+ mMagneticNotificationRowManager,
+ mSectionsManager);
}
static class LogMatcher implements ArgumentMatcher<LogMaker> {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 789701f5e4b0..766ae73cb49d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -405,7 +405,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
doNothing().when(mSwipeHelper).superSnapChild(mNotificationRow, 0, 0);
mSwipeHelper.snapChild(mNotificationRow, 0, 0);
- verify(mCallback, times(1)).onDragCancelled(mNotificationRow);
+ verify(mCallback, times(1)).onDragCancelledWithVelocity(mNotificationRow, 0);
verify(mSwipeHelper, times(1)).superSnapChild(mNotificationRow, 0, 0);
verify(mSwipeHelper, times(1)).handleMenuCoveredOrDismissed();
}
@@ -416,7 +416,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
doNothing().when(mSwipeHelper).superSnapChild(mNotificationRow, 10, 0);
mSwipeHelper.snapChild(mNotificationRow, 10, 0);
- verify(mCallback, times(1)).onDragCancelled(mNotificationRow);
+ verify(mCallback, times(1)).onDragCancelledWithVelocity(mNotificationRow, 0);
verify(mSwipeHelper, times(1)).superSnapChild(mNotificationRow, 10, 0);
verify(mSwipeHelper, times(0)).handleMenuCoveredOrDismissed();
}
@@ -426,7 +426,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
doNothing().when(mSwipeHelper).superSnapChild(mView, 10, 0);
mSwipeHelper.snapChild(mView, 10, 0);
- verify(mCallback).onDragCancelled(mView);
+ verify(mCallback).onDragCancelledWithVelocity(mView, 0);
verify(mSwipeHelper, never()).superSnapChild(mView, 10, 0);
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
index 87833d0c03f6..51de9d5d7514 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
@@ -6,8 +6,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -30,7 +32,7 @@ class NotificationTargetsHelperTest : SysuiTestCase() {
NotificationTestHelper(mContext, mDependency, TestableLooper.get(this), featureFlags)
}
- private fun notificationTargetsHelper() = NotificationTargetsHelper(featureFlags)
+ private fun notificationTargetsHelper() = NotificationTargetsHelper()
@Test
fun targetsForFirstNotificationInGroup() {
@@ -93,4 +95,71 @@ class NotificationTargetsHelperTest : SysuiTestCase() {
RoundableTargets(before = children.attachedChildren[1], swiped = swiped, after = null)
assertEquals(expected, actual)
}
+
+ @Test
+ fun findMagneticTargets_forMiddleChild_createsAllTargets() {
+ val childrenNumber = 5
+ val children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
+
+ // WHEN the swiped view is the one at the middle of the container
+ val swiped = children.attachedChildren[childrenNumber / 2]
+
+ // THEN all the views that surround it become targets with the swiped view at the middle
+ val actual =
+ notificationTargetsHelper()
+ .findMagneticTargets(viewSwiped = swiped, stackScrollLayout = stackScrollLayout, 5)
+ assertMagneticTargetsForChildren(actual, children.attachedChildren)
+ }
+
+ @Test
+ fun findMagneticTargets_forTopChild_createsEligibleTargets() {
+ val childrenNumber = 5
+ val children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
+
+ // WHEN the swiped view is the first one in the container
+ val swiped = children.attachedChildren[0]
+
+ // THEN the neighboring views become targets, with the swiped view at the middle and nulls
+ // to the left
+ val actual =
+ notificationTargetsHelper()
+ .findMagneticTargets(viewSwiped = swiped, stackScrollLayout = stackScrollLayout, 5)
+ val expectedRows =
+ listOf(null, null, swiped, children.attachedChildren[1], children.attachedChildren[2])
+ assertMagneticTargetsForChildren(actual, expectedRows)
+ }
+
+ @Test
+ fun findMagneticTargets_forBottomChild_createsEligibleTargets() {
+ val childrenNumber = 5
+ val children = notificationTestHelper.createGroup(childrenNumber).childrenContainer
+
+ // WHEN the view swiped is the last one in the container
+ val swiped = children.attachedChildren[childrenNumber - 1]
+
+ // THEN the neighboring views become targets, with the swiped view at the middle and nulls
+ // to the right
+ val actual =
+ notificationTargetsHelper()
+ .findMagneticTargets(viewSwiped = swiped, stackScrollLayout = stackScrollLayout, 5)
+ val expectedRows =
+ listOf(
+ children.attachedChildren[childrenNumber - 3],
+ children.attachedChildren[childrenNumber - 2],
+ swiped,
+ null,
+ null,
+ )
+ assertMagneticTargetsForChildren(actual, expectedRows)
+ }
+
+ private fun assertMagneticTargetsForChildren(
+ targets: List<MagneticRowListener?>,
+ children: List<ExpandableNotificationRow?>,
+ ) {
+ assertThat(targets.size).isEqualTo(children.size)
+ targets.forEachIndexed { i, target ->
+ assertThat(target).isEqualTo(children[i]?.magneticRowListener)
+ }
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index a045b37a8119..786b3590facb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -19,8 +19,6 @@
package com.android.systemui.statusbar.notification.stack.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
@@ -64,9 +62,11 @@ import com.android.systemui.scene.data.repository.Idle
import com.android.systemui.scene.data.repository.Transition
import com.android.systemui.scene.data.repository.setTransition
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.domain.interactor.enableDualShade
+import com.android.systemui.shade.domain.interactor.enableSingleShade
+import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.mockLargeScreenHeaderHelper
import com.android.systemui.shade.shadeTestUtil
-import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.HorizontalPosition
import com.android.systemui.testKosmos
@@ -143,7 +143,7 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
fun validateMarginStartInSplitShade() =
testScope.runTest {
- shadeTestUtil.setSplitShade(true)
+ kosmos.enableSplitShade()
overrideDimensionPixelSize(R.dimen.notification_panel_margin_horizontal, 20)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
@@ -156,7 +156,7 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
fun validateMarginStart() =
testScope.runTest {
- shadeTestUtil.setSplitShade(false)
+ kosmos.enableSingleShade()
overrideDimensionPixelSize(R.dimen.notification_panel_margin_horizontal, 20)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
@@ -169,9 +169,9 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
fun validateHorizontalPositionSingleShade() =
testScope.runTest {
+ kosmos.enableSingleShade()
overrideDimensionPixelSize(R.dimen.shade_panel_width, 200)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
- shadeTestUtil.setSplitShade(false)
val horizontalPosition = checkNotNull(dimens).horizontalPosition
assertIs<HorizontalPosition.EdgeToEdge>(horizontalPosition)
@@ -180,9 +180,9 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
fun validateHorizontalPositionSplitShade() =
testScope.runTest {
+ kosmos.enableSplitShade()
overrideDimensionPixelSize(R.dimen.shade_panel_width, 200)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
- shadeTestUtil.setSplitShade(true)
val horizontalPosition = checkNotNull(dimens).horizontalPosition
assertIs<HorizontalPosition.MiddleToEdge>(horizontalPosition)
@@ -191,25 +191,22 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
@EnableSceneContainer
- @DisableFlags(DualShade.FLAG_NAME)
fun validateHorizontalPositionInSceneContainerSingleShade() =
testScope.runTest {
+ kosmos.enableSingleShade()
overrideDimensionPixelSize(R.dimen.shade_panel_width, 200)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
- shadeTestUtil.setSplitShade(false)
val horizontalPosition = checkNotNull(dimens).horizontalPosition
assertIs<HorizontalPosition.EdgeToEdge>(horizontalPosition)
}
@Test
- @EnableSceneContainer
- @DisableFlags(DualShade.FLAG_NAME)
fun validateHorizontalPositionInSceneContainerSplitShade() =
testScope.runTest {
+ kosmos.enableSplitShade()
overrideDimensionPixelSize(R.dimen.shade_panel_width, 200)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
- shadeTestUtil.setSplitShade(true)
val horizontalPosition = checkNotNull(dimens).horizontalPosition
assertIs<HorizontalPosition.MiddleToEdge>(horizontalPosition)
@@ -218,12 +215,11 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
@EnableSceneContainer
- @EnableFlags(DualShade.FLAG_NAME)
fun validateHorizontalPositionInDualShade_narrowLayout() =
testScope.runTest {
+ kosmos.enableDualShade(wideLayout = false)
overrideDimensionPixelSize(R.dimen.shade_panel_width, 200)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
- shadeTestUtil.setSplitShade(false)
val horizontalPosition = checkNotNull(dimens).horizontalPosition
assertIs<HorizontalPosition.EdgeToEdge>(horizontalPosition)
@@ -231,12 +227,11 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
@EnableSceneContainer
- @EnableFlags(DualShade.FLAG_NAME)
fun validateHorizontalPositionInDualShade_wideLayout() =
testScope.runTest {
+ kosmos.enableDualShade(wideLayout = true)
overrideDimensionPixelSize(R.dimen.shade_panel_width, 200)
val dimens by collectLastValue(underTest.configurationBasedDimensions)
- shadeTestUtil.setSplitShade(true)
val horizontalPosition = checkNotNull(dimens).horizontalPosition
assertIs<HorizontalPosition.FloatAtStart>(horizontalPosition)
@@ -246,8 +241,8 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
fun validatePaddingTopInSplitShade_usesLargeHeaderHelper() =
testScope.runTest {
+ kosmos.enableSplitShade()
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
- shadeTestUtil.setSplitShade(true)
overrideResource(R.bool.config_use_large_screen_shade_header, true)
overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 10)
overrideDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin, 50)
@@ -262,8 +257,8 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
fun validatePaddingTopInNonSplitShade_usesLargeScreenHeader() =
testScope.runTest {
+ kosmos.enableSingleShade()
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(10)
- shadeTestUtil.setSplitShade(false)
overrideResource(R.bool.config_use_large_screen_shade_header, true)
overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 10)
overrideDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin, 50)
@@ -278,8 +273,8 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
@Test
fun validatePaddingTopInNonSplitShade_doesNotUseLargeScreenHeader() =
testScope.runTest {
+ kosmos.enableSingleShade()
whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(10)
- shadeTestUtil.setSplitShade(false)
overrideResource(R.bool.config_use_large_screen_shade_header, false)
overrideDimensionPixelSize(R.dimen.large_screen_shade_header_height, 10)
overrideDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin, 50)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 4e0393341faf..4313aea44326 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -36,7 +36,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.statusbar.StatusBarIcon
import com.android.settingslib.notification.modes.TestModeBuilder
-import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor
@@ -480,8 +479,6 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
override fun getZen(): Int = zen
- override fun getManualRule(): ZenModeConfig.ZenRule = throw NotImplementedError()
-
override fun getConfig(): ZenModeConfig = throw NotImplementedError()
override fun getConsolidatedPolicy(): NotificationManager.Policy = consolidatedPolicy
@@ -490,14 +487,6 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
override fun isZenAvailable() = throw NotImplementedError()
- override fun getEffectsSuppressor() = throw NotImplementedError()
-
- override fun isCountdownConditionSupported() = throw NotImplementedError()
-
override fun getCurrentUser() = throw NotImplementedError()
-
- override fun isVolumeRestricted() = throw NotImplementedError()
-
- override fun areNotificationsHiddenInShade() = throw NotImplementedError()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
index abfd64adab22..2e43e5273766 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
@@ -100,7 +100,9 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
@After
fun tearDown() {
- ViewUtils.detachView(view)
+ if (::view.isInitialized) {
+ ViewUtils.detachView(view)
+ }
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt
index 9abdf42e735c..22250082944e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt
@@ -91,45 +91,6 @@ class ZenModeControllerImplTest : SysuiTestCase() {
}
@Test
- fun testAreNotificationsHiddenInShade_zenOffShadeSuppressed() {
- config.suppressedVisualEffects =
- NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
- controller.updateZenMode(Settings.Global.ZEN_MODE_OFF)
- controller.updateZenModeConfig()
- assertThat(controller.areNotificationsHiddenInShade()).isFalse()
- }
-
- @Test
- fun testAreNotificationsHiddenInShade_zenOnShadeNotSuppressed() {
- val policy =
- NotificationManager.Policy(
- 0,
- 0,
- 0,
- NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR,
- )
- whenever(mNm.consolidatedNotificationPolicy).thenReturn(policy)
- controller.updateConsolidatedNotificationPolicy()
- controller.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
- assertThat(controller.areNotificationsHiddenInShade()).isFalse()
- }
-
- @Test
- fun testAreNotificationsHiddenInShade_zenOnShadeSuppressed() {
- val policy =
- NotificationManager.Policy(
- 0,
- 0,
- 0,
- NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST,
- )
- whenever(mNm.consolidatedNotificationPolicy).thenReturn(policy)
- controller.updateConsolidatedNotificationPolicy()
- controller.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
- assertThat(controller.areNotificationsHiddenInShade()).isTrue()
- }
-
- @Test
fun testModeChange() =
testScope.runTest {
val states =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt
index 89410593fe62..b4fbaad6ab37 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/GradientColorWallpaperTest.kt
@@ -18,6 +18,7 @@ package com.android.systemui.wallpapers
import android.app.Flags
import android.content.Context
+import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
@@ -31,14 +32,18 @@ import android.view.SurfaceHolder
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.res.R
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.spy
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
+import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyZeroInteractions
import org.mockito.kotlin.whenever
@@ -56,6 +61,8 @@ class GradientColorWallpaperTest : SysuiTestCase() {
@Mock private lateinit var mockContext: Context
+ @Mock private lateinit var mockResources: Resources
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -64,6 +71,13 @@ class GradientColorWallpaperTest : SysuiTestCase() {
whenever(surfaceHolder.surfaceFrame).thenReturn(surfaceFrame)
whenever(surface.lockHardwareCanvas()).thenReturn(canvas)
whenever(mockContext.getColor(anyInt())).thenReturn(1)
+ whenever(mockContext.resources).thenReturn(mockResources)
+ whenever(
+ mockResources.getDimensionPixelOffset(
+ eq(R.dimen.gradient_color_wallpaper_center_offset)
+ )
+ )
+ .thenReturn(OFFSET_PX)
}
private fun createGradientColorWallpaperEngine(): Engine {
@@ -93,9 +107,11 @@ class GradientColorWallpaperTest : SysuiTestCase() {
engine.onSurfaceRedrawNeeded(surfaceHolder)
verify(canvas).drawRect(any<RectF>(), any<Paint>())
+ verify(canvas, times(2)).drawCircle(anyFloat(), anyFloat(), anyFloat(), any<Paint>())
}
private companion object {
val surfaceFrame = Rect(0, 0, 100, 100)
+ const val OFFSET_PX = 100
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockLogger.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockLogger.kt
new file mode 100644
index 000000000000..6a9bbca1d4e1
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockLogger.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.plugins.clocks
+
+import android.view.View
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.core.LogcatOnlyMessageBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.core.MessageBuffer
+import kotlin.math.abs
+
+class ClockLogger(private val view: View?, buffer: MessageBuffer, tag: String) :
+ Logger(buffer, tag) {
+
+ private var loggedAlpha = 1000f
+ private val isDrawn: Boolean
+ get() = ((view?.mPrivateFlags ?: 0x0) and 0x20 /* PFLAG_DRAWN */) > 0
+
+ fun invalidate() {
+ if (isDrawn && view?.visibility == View.VISIBLE) {
+ d("invalidate()")
+ }
+ }
+
+ fun refreshTime() {
+ d("refreshTime()")
+ }
+
+ fun requestLayout() {
+ if (view?.isLayoutRequested() == false) {
+ d("requestLayout()")
+ }
+ }
+
+ fun onMeasure() {
+ d("onMeasure()")
+ }
+
+ fun onLayout() {
+ d("onLayout()")
+ }
+
+ fun onDraw() {
+ d("onDraw()")
+ }
+
+ fun onDraw(str: String?) {
+ d({ "onDraw(${escapeTime(str1)})" }) { str1 = str ?: "" }
+ }
+
+ fun onDraw(lsStr: String?, aodStr: String?) {
+ d({ "onDraw(ls = ${escapeTime(str1)}, aod = ${escapeTime(str2)}" }) {
+ str1 = lsStr
+ str2 = aodStr
+ }
+ }
+
+ fun setVisibility(visibility: Int) {
+ if (visibility != view?.visibility) {
+ d({ "setVisibility(${getVisText(int1)})" }) { int1 = visibility }
+ }
+ }
+
+ fun setAlpha(alpha: Float) {
+ val delta = if (alpha <= 0f || alpha >= 1f) 0.001f else 0.5f
+ if (abs(loggedAlpha - alpha) >= delta) {
+ loggedAlpha = alpha
+ d({ "setAlpha($double1)" }) { double1 = alpha.toDouble() }
+ }
+ }
+
+ fun addView(child: View) {
+ d({ "addView($str1 @$int1)" }) {
+ str1 = child::class.simpleName!!
+ int1 = child.id
+ }
+ }
+
+ companion object {
+ // Used when MessageBuffers are not provided by the host application
+ val DEFAULT_MESSAGE_BUFFER = LogcatOnlyMessageBuffer(LogLevel.INFO)
+
+ // Debug is primarially used for tests, but can also be used for tracking down hard issues.
+ val DEBUG_MESSAGE_BUFFER = LogcatOnlyMessageBuffer(LogLevel.DEBUG)
+
+ // Only intended for use during initialization steps before the logger is initialized
+ val INIT_LOGGER = ClockLogger(null, LogcatOnlyMessageBuffer(LogLevel.ERROR), "CLOCK_INIT")
+
+ @JvmStatic
+ fun getVisText(visibility: Int): String {
+ return when (visibility) {
+ View.GONE -> "GONE"
+ View.INVISIBLE -> "INVISIBLE"
+ View.VISIBLE -> "VISIBLE"
+ else -> "$visibility"
+ }
+ }
+
+ @JvmStatic
+ fun escapeTime(timeStr: String?): String? {
+ return timeStr?.replace("\n", "\\n")
+ }
+ }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt
index 50b3f78a49bc..8a962f9078e6 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt
@@ -25,34 +25,34 @@ interface TableLogBufferBase {
*
* For Java overloading.
*/
- fun logChange(prefix: String, columnName: String, value: String?) {
+ fun logChange(prefix: String = "", columnName: String, value: String?) {
logChange(prefix, columnName, value, isInitial = false)
}
/** Logs a String? change. */
- fun logChange(prefix: String, columnName: String, value: String?, isInitial: Boolean)
+ fun logChange(prefix: String = "", columnName: String, value: String?, isInitial: Boolean)
/**
* Logs a Boolean change.
*
* For Java overloading.
*/
- fun logChange(prefix: String, columnName: String, value: Boolean) {
+ fun logChange(prefix: String = "", columnName: String, value: Boolean) {
logChange(prefix, columnName, value, isInitial = false)
}
/** Logs a Boolean change. */
- fun logChange(prefix: String, columnName: String, value: Boolean, isInitial: Boolean)
+ fun logChange(prefix: String = "", columnName: String, value: Boolean, isInitial: Boolean)
/**
* Logs an Int? change.
*
* For Java overloading.
*/
- fun logChange(prefix: String, columnName: String, value: Int?) {
+ fun logChange(prefix: String = "", columnName: String, value: Int?) {
logChange(prefix, columnName, value, isInitial = false)
}
/** Logs an Int? change. */
- fun logChange(prefix: String, columnName: String, value: Int?, isInitial: Boolean)
+ fun logChange(prefix: String = "", columnName: String, value: Int?, isInitial: Boolean)
}
diff --git a/packages/SystemUI/res-keyguard/layout/bouncer_message_view.xml b/packages/SystemUI/res-keyguard/layout/bouncer_message_view.xml
index f7dac13888c0..ea494b4642d5 100644
--- a/packages/SystemUI/res-keyguard/layout/bouncer_message_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/bouncer_message_view.xml
@@ -21,7 +21,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyguard_lock_padding"
- android:focusable="true"
+ android:focusable="false"
/>
<com.android.keyguard.BouncerKeyguardMessageArea
@@ -30,6 +30,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/secondary_message_padding"
- android:focusable="true" />
+ android:focusable="false" />
</merge>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
index 2a8f1b596711..f231df2f1a10 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_motion_layout.xml
@@ -66,7 +66,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
- android:importantForAccessibility="noHideDescendants"
+ android:screenReaderFocusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index 76f6f599c54c..04457229d573 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -31,7 +31,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
- android:importantForAccessibility="noHideDescendants"
+ android:screenReaderFocusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml
index 5879c110d8a1..b184344f2f24 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_motion_layout.xml
@@ -67,7 +67,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
- android:importantForAccessibility="noHideDescendants"
+ android:screenReaderFocusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
index 3f7b02835357..0e15ff66f3ee 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
@@ -35,7 +35,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
- android:importantForAccessibility="noHideDescendants"
+ android:screenReaderFocusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml
index b464fb3bafed..f6ac02aee657 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_motion_layout.xml
@@ -74,7 +74,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
- android:importantForAccessibility="noHideDescendants"
+ android:screenReaderFocusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 21580731aed2..ba4da794d777 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -32,7 +32,7 @@
<com.android.systemui.bouncer.ui.BouncerMessageView
android:id="@+id/bouncer_message_view"
- android:importantForAccessibility="noHideDescendants"
+ android:screenReaderFocusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml b/packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml
index cc99f5e125f3..dd5f7e4e2ed4 100644
--- a/packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml
+++ b/packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml
@@ -30,7 +30,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:textAppearance="@style/TextAppearance.QS.Status.Carriers"
+ android:textAppearance="@style/TextAppearance.QS.Status"
android:layout_marginEnd="@dimen/qs_carrier_margin_width"
android:visibility="gone"
android:textDirection="locale"
diff --git a/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml b/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml
index e47fc62c6e16..8944efb99f69 100644
--- a/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml
+++ b/packages/SystemUI/res/layout/keyguard_settings_popup_menu.xml
@@ -42,7 +42,6 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@androidprv:color/materialColorOnSecondaryFixed"
- android:textSize="14sp"
android:maxLines="1"
android:ellipsize="end" />
diff --git a/packages/SystemUI/res/layout/low_light_clock_dream.xml b/packages/SystemUI/res/layout/low_light_clock_dream.xml
new file mode 100644
index 000000000000..3d74a9fd8ae3
--- /dev/null
+++ b/packages/SystemUI/res/layout/low_light_clock_dream.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/low_light_clock_dream"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/low_light_clock_background_color">
+
+ <TextClock
+ android:id="@+id/low_light_text_clock"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/low_light_clock_text_size"
+ android:layout_gravity="center"
+ android:fontFamily="google-sans-clock"
+ android:gravity="center_horizontal"
+ android:textColor="@color/low_light_clock_text_color"
+ android:autoSizeTextType="uniform"
+ android:autoSizeMaxTextSize="@dimen/low_light_clock_text_size"
+ android:format12Hour="h:mm"
+ android:format24Hour="H:mm"/>
+
+ <TextView
+ android:id="@+id/charging_status_text_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
+ android:gravity="center"
+ android:minHeight="@dimen/low_light_clock_charging_text_min_height"
+ android:layout_gravity="center_horizontal|bottom"
+ android:paddingStart="@dimen/keyguard_indication_text_padding"
+ android:paddingEnd="@dimen/keyguard_indication_text_padding"
+ android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+ android:textSize="@dimen/low_light_clock_charging_text_size"
+ android:textFontWeight="@integer/low_light_clock_charging_text_font_weight"
+ android:maxLines="2"
+ android:ellipsize="end"
+ android:accessibilityLiveRegion="polite" />
+ </FrameLayout>
+
diff --git a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
index 21e0d2c0b8d7..69117cf7cf5d 100644
--- a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
@@ -52,13 +52,13 @@
android:layout_height="64dp"
android:focusable="false"
android:importantForAccessibility="no"
- android:background="@drawable/media_output_title_icon_area"
android:layout_gravity="center_vertical|start">
<ImageView
android:id="@+id/title_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:focusable="false"
+ android:contentDescription="@null"
android:importantForAccessibility="no"
android:animateLayoutChanges="true"
android:layout_gravity="center"/>
@@ -75,30 +75,17 @@
android:visibility="gone"/>
</FrameLayout>
- <TextView
- android:id="@+id/title"
- android:focusable="false"
- android:importantForAccessibility="no"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:layout_marginStart="72dp"
- android:layout_marginEnd="56dp"
- android:ellipsize="end"
- android:maxLines="1"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- android:textSize="16sp"/>
-
<LinearLayout
- android:id="@+id/two_line_layout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical|start"
+ android:gravity="center_vertical|start"
android:layout_height="48dp"
android:layout_marginEnd="56dp"
android:layout_marginStart="72dp">
<TextView
- android:id="@+id/two_line_title"
+ android:id="@+id/title"
+ android:importantForAccessibility="no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
diff --git a/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml b/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml
index 3ca4b94d3003..aefe92798c99 100644
--- a/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml
+++ b/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml
@@ -77,6 +77,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/privacy_dialog_item_header_expanded_layout"
+ android:importantForAccessibility="no"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/shade_carrier.xml b/packages/SystemUI/res/layout/shade_carrier.xml
index 0fed393a7ed3..6a5df9c3ed10 100644
--- a/packages/SystemUI/res/layout/shade_carrier.xml
+++ b/packages/SystemUI/res/layout/shade_carrier.xml
@@ -33,7 +33,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:textAppearance="@style/TextAppearance.QS.Status.Carriers"
+ android:textAppearance="@style/TextAppearance.QS.Status"
android:textDirection="locale"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
diff --git a/packages/SystemUI/res/layout/shade_carrier_group.xml b/packages/SystemUI/res/layout/shade_carrier_group.xml
index 2e8f98cbd190..6551f3b8160d 100644
--- a/packages/SystemUI/res/layout/shade_carrier_group.xml
+++ b/packages/SystemUI/res/layout/shade_carrier_group.xml
@@ -32,7 +32,7 @@
android:minWidth="48dp"
android:minHeight="48dp"
android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.QS.Status.Carriers.NoCarrierText"
+ android:textAppearance="@style/TextAppearance.QS.Status"
android:textDirection="locale"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 91d92a21ddf1..e7efdba446a7 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Sluitskermlegstukke"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Om ’n app met ’n legstuk oop te maak, sal jy moet verifieer dat dit jy is. Hou ook in gedagte dat enigeen dit kan bekyk, selfs wanneer jou tablet gesluit is. Sommige legstukke is moontlik nie vir jou sluitskerm bedoel nie en dit kan onveilig wees om dit hier by te voeg."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Het dit"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Legstukke"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Maak seker dat “Wys legstukke op sluitskerm” in instellings geaktiveer is om die “Legstukke”-kortpad by te voeg."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Instellings"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Wys sluimerskermknoppie"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Wissel gebruiker"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aftrekkieslys"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle programme en data in hierdie sessie sal uitgevee word."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Dateer tans op"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Ouerkontroles"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Jy sal nie jou volgende wekker <xliff:g id="WHEN">%1$s</xliff:g> hoor nie"</string>
<string name="alarm_template" msgid="2234991538018805736">"om <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"op <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Word aan die bokant van gesprekskennisgewings en as \'n profielfoto op sluitskerm gewys, verskyn as \'n borrel, onderbreek Moenie Steur Nie"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> steun nie gesprekskenmerke nie"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Hierdie kennisgewings kan nie gewysig word nie."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Oproepkennisgewings kan nie gewysig word nie."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Hierdie groep kennisgewings kan nie hier opgestel word nie"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Sakrekenaar"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Moenie Steur Nie"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volumeknoppieskortpad"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Stelselapps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Verrigting van veelvuldige take"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Verdeelde skerm"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Toeganklikheid"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Invoer"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Appkortpaaie"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Huidige app"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Jy het die Bekyk Onlangse Apps-gebaar voltooi."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Swiep op en hou met drie vingers op jou raakpaneel om onlangse apps te bekyk"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Wissel apps"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Uitstekende werk!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Jy het die “wissel tussen apps”-gebaar voltooi."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Bekyk alle apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Druk die handelingsleutel op jou sleutelbord"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 6e079a2a647f..76a38c921b2d 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"የማያ ገፅ ቁልፍ ምግብሮች"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ምግብር በመጠቀም መተግበሪያ ለመክፈት እርስዎ መሆንዎን ማረጋገጥ አለብዎት። እንዲሁም የእርስዎ ጡባዊ በተቆለፈበት ጊዜ እንኳን ማንኛውም ሰው እነሱን ማየት እንደሚችል ከግምት ውስጥ ያስገቡ። አንዳንድ ምግብሮች ለማያ ገፅ ቁልፍዎ የታሰቡ ላይሆኑ ይችላሉ እና እዚህ ለማከል አስተማማኝ ላይሆኑ ይችላሉ።"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ገባኝ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ምግብሮች"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"የ«ምግብሮች» አቋራጭን ለማከል በቅንብሮች ውስጥ «ምግብሮችን በማያ ገፅ ቁልፍ ላይ አሳይ» የሚለው መንቃቱን ያረጋግጡ።"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ቅንብሮች"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"የገፀ ማያ አሳራፊ አዝራርን አሳይ"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ተጠቃሚ ቀይር"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ወደታች ተጎታች ምናሌ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"በዚህ ክፍለ-ጊዜ ውስጥ ያሉ ሁሉም መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"በማዘመን ላይ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"የስራ መገለጫ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"የአውሮፕላን ሁነታ"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"የወላጅ መቆጣጠሪያዎች"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"የእርስዎን ቀጣይ ማንቂያ <xliff:g id="WHEN">%1$s</xliff:g> አይሰሙም"</string>
<string name="alarm_template" msgid="2234991538018805736">"በ<xliff:g id="WHEN">%1$s</xliff:g> ላይ"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"በ<xliff:g id="WHEN">%1$s</xliff:g> ላይ"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"በውይይት ማሳወቂያዎች አናት ላይ እና በማያ ገፅ መቆለፊያ ላይ እንደ መገለጫ ምስል ይታያል፣ እንደ አረፋ ሆኖ ይታያል፣ አትረብሽን ያቋርጣል"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ቅድሚያ"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> የውይይት ባህሪያትን አይደግፍም"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"እነዚህ ማሳወቂያዎች ሊሻሻሉ አይችሉም።"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"የጥሪ ማሳወቂያዎች ሊቀየሩ አይችሉም።"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"የማሳወቂያዎች ይህ ቡድን እዚህ ላይ ሊዋቀር አይችልም"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"የቀን መቁጠሪያ"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ሒሳብ ማስያ"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ካርታዎች"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"አትረብሽ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"የድምፅ አዝራሮች አቋራጭ"</string>
<string name="battery" msgid="769686279459897127">"ባትሪ"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"የሥርዓት መተግበሪያዎች"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ብዙ ተግባራትን በተመሳሳይ ጊዜ ማከናወን"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"የተከፈለ ማያ ገፅ"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ተደራሽነት"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ግብዓት"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"የመተግበሪያ አቋራጮች"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"የአሁን መተግበሪያ"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"የቅርብ ጊዜ መተግበሪያዎች አሳይ ምልክትን አጠናቅቀዋል።"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"የቅርብ ጊዜ መተግበሪያዎችን ለማየት የመዳሰሻ ሰሌዳዎ ላይ ሦስት ጣቶችን በመጠቀም ወደላይ ያንሸራትቱ እና ይያዙ"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"መተግበሪያዎችን ይቀያይሩ"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"ጥሩ ሠርተዋል!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"የመተግበሪያ ምልክቶችን ይቀይሩ የሚለወን አጠናቅቀዋል።"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"ሁሉንም መተግበሪያዎች ይመልከቱ"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"በቁልፍ ሰሌዳዎ ላይ ያለውን የተግባር ቁልፍ ይጫኑ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 7896cdbd68f8..7db9a0d22ec6 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"التطبيقات المصغّرة المصمَّمة لشاشة القفل"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"لفتح تطبيق باستخدام تطبيق مصغَّر، عليك إثبات هويتك. يُرجى ملاحظة أنّ أي شخص يمكنه الاطّلاع محتوى التطبيقات المصغَّرة، حتى وإن كان جهازك اللوحي مُقفلاً. بعض التطبيقات المصغّرة قد لا تكون مُصمَّمة لإضافتها إلى شاشة القفل، وقد يكون هذا الإجراء غير آمن."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"حسنًا"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"التطبيقات المصغَّرة"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"لإضافة اختصار \"التطبيقات المصغّرة\"، يجب تفعيل خيار \"عرض التطبيقات المصغّرة على شاشة القفل\" من خلال الإعدادات."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"الإعدادات"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"زر \"إظهار شاشة الاستراحة\""</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تبديل المستخدم"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"القائمة المنسدلة"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"سيتم حذف كل التطبيقات والبيانات في هذه الجلسة."</string>
@@ -802,6 +805,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"تظهر في أعلى إشعارات المحادثات وكصورة ملف شخصي على شاشة القفل وتظهر على شكل فقاعة لمقاطعة ميزة \"عدم الإزعاج\"."</string>
<string name="notification_priority_title" msgid="2079708866333537093">"الأولوية"</string>
<string name="no_shortcut" msgid="8257177117568230126">"لا يدعم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> ميزات المحادثات."</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"يتعذّر تعديل هذه الإشعارات."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"لا يمكن تعديل إشعارات المكالمات."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"يتعذّر ضبط مجموعة الإشعارات هذه هنا."</string>
@@ -912,6 +919,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"‏تقويم Google"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"الآلة الحاسبة"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"‏خرائط Google"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"عدم الإزعاج"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"اختصار أزرار مستوى الصوت"</string>
<string name="battery" msgid="769686279459897127">"البطارية"</string>
@@ -1497,11 +1514,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"لقد أكملْت التدريب على إيماءة عرض التطبيقات المستخدَمة مؤخرًا."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"لعرض التطبيقات المستخدَمة مؤخرًا، يُرجى التمرير سريعًا للأعلى مع الاستمرار باستخدام ثلاثة أصابع على لوحة اللمس"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"التبديل بين التطبيقات"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"أحسنت صنعًا."</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"أكملت التدريب على إيماءة التبديل بين التطبيقات."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"عرض جميع التطبيقات"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"اضغط على مفتاح الإجراء في لوحة المفاتيح"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 7c99df9a8c78..297b41059ebc 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"লক স্ক্ৰীন ৱিজেট"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"এটা ৱিজেট ব্যৱহাৰ কৰি কোনো এপ্ খুলিবলৈ, এয়া আপুনিয়েই বুলি সত্যাপন পৰীক্ষা কৰিব লাগিব। লগতে, মনত ৰাখিব যে যিকোনো লোকেই সেইবোৰ চাব পাৰে, আনকি আপোনাৰ টেবলেটটো লক হৈ থাকিলেও। কিছুমান ৱিজেট হয়তো আপোনাৰ লক স্ক্ৰীনৰ বাবে কৰা হোৱা নাই আৰু ইয়াত যোগ কৰাটো অসুৰক্ষিত হ’ব পাৰে।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"বুজি পালোঁ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ৱিজেট"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"ৱিজেট\"ৰ শ্বৰ্টকাট যোগ দিবলৈ, ছেটিঙত \"লক স্ক্ৰীনত ৱিজেট দেখুৱাওক\" সক্ষম কৰি থোৱাটো নিশ্চিত কৰক।"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ছেটিং"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"স্ক্ৰীনছেভাৰৰ বুটাম দেখুৱাওক"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যৱহাৰকাৰী সলনি কৰক"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুল-ডাউনৰ মেনু"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ আটাইবোৰ এপ্ আৰু ডেটা মচা হ\'ব।"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"আপডে’ট কৰি থকা হৈছে"</string>
<string name="status_bar_work" msgid="5238641949837091056">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"এয়াৰপ্লে’ন ম’ড"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"অভিভাৱকীয় নিয়ন্ত্ৰণ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"আপুনি আপোনাৰ পিছৰটো এলাৰ্ম <xliff:g id="WHEN">%1$s</xliff:g> বজাত শুনা নাপাব"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> বজাত"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> বজাত"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"বাৰ্তালাপৰ জাননীৰ শীৰ্ষত আৰু প্ৰ’ফাইল চিত্ৰ হিচাপে লক স্ক্ৰীনত দেখুৱায়, এটা বাবল হিচাপে দেখা পোৱা যায়, অসুবিধা নিদিব ম’ডত ব্যাঘাত জন্মায়"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"অগ্ৰাধিকাৰ"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বাৰ্তালাপৰ সুবিধাসমূহ সমৰ্থন নকৰে"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"এই জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"কলৰ জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"এই ধৰণৰ জাননীবোৰ ইয়াত কনফিগাৰ কৰিব পৰা নাযায়"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"কেলকুলেটৰ"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"মেপ"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"অসুবিধা নিদিব"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বুটামসমূহৰ শ্বৰ্টকাট"</string>
<string name="battery" msgid="769686279459897127">"বেটাৰী"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"ছিষ্টেম এপ্‌"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"মাল্টিটাস্কিং"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"বিভাজিত স্ক্ৰীন"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"সাধ্য সুবিধা"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ইনপুট"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"এপ্ শ্বৰ্টকাটসমূহ"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"বৰ্তমানৰ এপ্‌"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"আপুনি শেহতীয়া এপ্ চোৱাৰ নিৰ্দেশনাটো সম্পূৰ্ণ কৰিছে।"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"শেহতীয়া এপ্‌সমূহ চাবলৈ, আপোনাৰ টাচ্চপেডত তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"এপ্‌সমূহ সলনি কৰক"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"বঢ়িয়া!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"আপুনি এপ্‌ সলনি কৰাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"আটাইবোৰ এপ্ চাওক"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 64b2726f26d8..fb13ac4a3c64 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kilid ekranı vidcetləri"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Vidcetdən istifadə edərək tətbiqi açmaq üçün kimliyi doğrulamalısınız. Planşet kilidli olsa da, hər kəs vidcetlərə baxa bilər. Bəzi vidcetlər kilid ekranı üçün nəzərdə tutulmayıb və bura əlavə etmək təhlükəli ola bilər."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Anladım"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidcetlər"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Vidcetlər\" qısayolunu əlavə etmək üçün ayarlarda \"Vidcetləri kilidli ekranda göstərin\" seçimi aktiv olmalıdır."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ayarlar"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Ekran qoruyucu düyməsini göstərin"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aşağı çəkilən menyu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu sessiyada bütün tətbiqlər və data silinəcək."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Güncəllənir"</string>
<string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Təyyarə rejimi"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Valideyn nəzarətləri"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> zaman növbəti xəbərdarlığınızı eşitməyəcəksiniz"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Söhbət bildirişlərinin yuxarısında və kilid ekranında profil şəkli kimi göstərilir, baloncuq kimi görünür, Narahat Etməyin rejimini kəsir"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> söhbət funksiyalarını dəstəkləmir"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirişlər dəyişdirilə bilməz."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Zəng bildirişləri dəyişdirilə bilməz."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Bu bildiriş qrupunu burada konfiqurasiya etmək olmaz"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Təqvim"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulyator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Xəritə"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Narahat Etməyin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Səs düymələri qısayolu"</string>
<string name="battery" msgid="769686279459897127">"Batareya"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Sistem tətbiqləri"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Çoxsaylı tapşırıq icrası"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Bölünmüş ekran"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Xüsusi imkanlar"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Daxiletmə"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Tətbiq qısayolları"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Cari tətbiq"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Son tətbiqlərə baxmaq jestini tamamladınız."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Ən son tətbiqlərə baxmaq üçün taçpeddə üç barmağınızla yuxarı çəkin və saxlayın"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Başqa tətbiqə keçin"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Əla!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Tətbiqlərarası keçid jestini tamamladınız."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Bütün tətbiqlərə baxın"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Klaviaturada fəaliyyət açarına basın"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 31566929dae0..be65e9e108c8 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Vidžeti za zaključani ekran"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da biste otvorili aplikaciju koja koristi vidžet, treba da potvrdite da ste to vi. Imajte u vidu da svako može da ga vidi, čak i kada je tablet zaključan. Neki vidžeti možda nisu namenjeni za zaključani ekran i možda nije bezbedno da ih tamo dodate."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Važi"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidžeti"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Da biste dodali prečicu Vidžeti, uverite se da je u podešavanjima omogućeno Prikazuj vidžete na zaključanom ekranu."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Podešavanja"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Dugme Prikaži čuvar ekrana"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Istražite režim centra"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Pristupajte omiljenim vidžetima i čuvarima ekrana tokom punjenja."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Idemo"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zameni korisnika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ažurira se"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Režim rada u avionu"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Roditeljski nadzor"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sledeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikazuje se u vrhu obaveštenja o konverzacijama i kao slika profila na zaključanom ekranu, pojavljuje se kao oblačić, prekida režim Ne uznemiravaj"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritetno"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava funkcije konverzacije"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ova obaveštenja ne mogu da se menjaju."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obaveštenja o pozivima ne mogu da se menjaju."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ova grupa obaveštenja ne može da se konfiguriše ovde"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mape"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne uznemiravaj"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Prečica za dugmad za jačinu zvuka"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Sistemske aplikacije"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Obavljanje više zadataka istovremeno"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Podeljeni ekran"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Pristupačnost"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Unos"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Prečice za aplikacije"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aktuelna aplikacija"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Dovršili ste pokret za prikazivanje nedavno korišćenih aplikacija."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Da biste pregledali nedavne aplikacije, prevucite nagore i zadržite sa tri prsta na tačpedu"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Pređi na drugu aplikaciju"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Prevucite udesno sa četiri prsta na tačpedu"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Odlično!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Dovršili ste pokret za promenu aplikacija."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Prevucite ulevo sa četiri prsta na tačpedu da biste prešli na drugu aplikaciju"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Prikaži sve aplikacije"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite taster radnji na tastaturi"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Odlično!"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 5e339a4ea07e..ae73144ed21c 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Віджэты на экране блакіроўкі"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Каб адкрыць праграму з дапамогай віджэта, вам неабходна будзе пацвердзіць сваю асобу. Таксама памятайце, што такія віджэты могуць пабачыць іншыя людзі, нават калі экран планшэта заблакіраваны. Некаторыя віджэты могуць не падыходзіць для выкарыстання на экране блакіроўкі, і дадаваць іх сюды можа быць небяспечна."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Зразумела"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Віджэты"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Каб дадаць спалучэнне клавіш \"Віджэты\", у наладах павінна быць уключана функцыя \"Паказваць віджэты на экране блакіроўкі\"."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Налады"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Кнопка \"Паказаць застаўку\""</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Перайсці да іншага карыстальніка"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"высоўнае меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Абнаўленне…"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Працоўны профіль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Рэжым палёту"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Бацькоўскі кантроль"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Вы не пачуеце наступны будзільнік <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"З’яўляецца ўверсе раздзела размоў як усплывальнае апавяшчэнне, якое перарывае рэжым \"Не турбаваць\" і паказвае на экране блакіроўкі відарыс профілю"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Прыярытэт"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не падтрымлівае функцыі размовы"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Гэтыя апавяшчэнні нельга змяніць."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Апавяшчэнні пра выклікі нельга змяніць."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Тут канфігурыраваць гэту групу апавяшчэнняў забаронена"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Каляндар"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калькулятар"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карты"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не турбаваць"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Доступ праз кнопкі рэгулявання гучнасці"</string>
<string name="battery" msgid="769686279459897127">"Акумулятар"</string>
@@ -1497,11 +1513,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Вы скончылі вывучэнне жэсту для прагляду нядаўніх праграм."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Каб праглядзець нядаўнія праграмы, правядзіце трыма пальцамі ўверх па сэнсарным экране і затрымайце пальцы"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Пераключэнне праграм"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Выдатная праца!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Вы навучыліся рабіць жэст пераключэння праграм."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Глядзець усе праграмы"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Націсніце клавішу дзеяння на клавіятуры"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 245711f831b5..db253db73138 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Приспособления за заключения екран"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"За да отворите дадено приложение посредством приспособление, ще трябва да потвърдите, че това сте вие. Също така имайте предвид, че всеки ще вижда приспособленията дори когато таблетът ви е заключен. Възможно е някои от тях да не са предназначени за заключения екран и добавянето им на него може да е опасно."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Разбрах"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Приспособления"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"За да добавите пряк път към „Приспособления“, уверете се, че опцията „Показване на приспособленията на заключения екран“ е активирана в настройките."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Настройки"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Бутон за показване на скрийнсейвъра"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Превключване между потребителите"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падащо меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Всички приложения и данни в тази сесия ще бъдат изтрити."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Актуализира се"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Родителски контроли"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"в/ъв <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Показва се в горната част на известията за разговори и като снимка на потребителския профил на заключения екран, изглежда като балонче, прекъсва режима „Не безпокойте“"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддържа функциите за разговор"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Тези известия не могат да бъдат променяни."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Известията за обаждания не могат да бъдат променяни."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Тази група от известия не може да бъде конфигурирана тук"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калкулатор"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карти"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не безпокойте"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Пряк път към бутоните за силата на звука"</string>
<string name="battery" msgid="769686279459897127">"Батерия"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Системни приложения"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Няколко задачи едновременно"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Разделен екран"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Достъпност"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Въвеждане"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Преки пътища към приложения"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Текущо приложение"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Изпълнихте жеста за преглед на скорошните приложения."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"За да прегледате скорошните приложения, плъзнете три пръста нагоре по сензорния панел и задръжте"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Превключване на приложенията"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Отлично!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Изпълнихте жеста за превключване между приложения."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Преглед на всички приложения"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Натиснете клавиша за действия на клавиатурата си"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 42a4d540c0c8..5e9860d4aa55 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"লক স্ক্রিন উইজেট"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"উইজেট ব্যবহার করে কোনও অ্যাপ খুলতে, আপনাকে নিজের পরিচয় যাচাই করতে হবে। এছাড়াও, মনে রাখবেন, আপনার ট্যাবলেট লক থাকলেও যেকেউ তা দেখতে পারবেন। কিছু উইজেট আপনার লক স্ক্রিনের উদ্দেশ্যে তৈরি করা হয়নি এবং এখানে যোগ করা নিরাপদ নাও হতে পারে।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"বুঝেছি"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"উইজেট"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"উইজেট\" শর্টকার্ট যোগ করতে, সেটিংস থেকে \"লক স্ক্রিনে উইজেট দেখুন\" বিকল্প চালু আছে কিনা তা নিশ্চিত করুন।"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"সেটিংস"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"স্ক্রিন সেভার বোতাম দেখুন"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যবহারকারী পাল্টে দিন"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুলডাউন মেনু"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই সেশনের সব অ্যাপ ও ডেটা মুছে ফেলা হবে।"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"আপডেট করা হচ্ছে"</string>
<string name="status_bar_work" msgid="5238641949837091056">"কাজের প্রোফাইল"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"বিমান মোড"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"অভিভাবকীয় নিয়ন্ত্রণ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"আপনি আপনার পরবর্তী <xliff:g id="WHEN">%1$s</xliff:g> অ্যালার্ম শুনতে পাবেন না"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> -তে"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"কথোপকথনের বিজ্ঞপ্তির উপরের দিকে এবং প্রোফাইল ছবি হিসেবে লক স্ক্রিনে দেখানো হয়, বাবল হিসেবেও এটি দেখা যায় এবং এর ফলে \'বিরক্ত করবে না\' মোডে কাজ করতে অসুবিধা হয়"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"অগ্রাধিকার"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এ কথোপকথন ফিচার কাজ করে না"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"এই বিজ্ঞপ্তিগুলি পরিবর্তন করা যাবে না।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"কল বিজ্ঞপ্তি পরিবর্তন করা যাবে না।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"এই সমস্ত বিজ্ঞপ্তিকে এখানে কনফিগার করা যাবে না"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ক্যালকুলেটর"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ম্যাপ"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"বিরক্ত করবে না"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বোতামের শর্টকাট"</string>
<string name="battery" msgid="769686279459897127">"ব্যাটারি"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"সিস্টেম অ্যাপ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"মাল্টিটাস্কিং"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"স্প্লিট স্ক্রিন"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"অ্যাক্সেসিবিলিটি"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ইনপুট"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"অ্যাপ শর্টকাট"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"বর্তমান অ্যাপ"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"সম্প্রতি ব্যবহার করা হয়েছে এমন অ্যাপের জেসচার দেখা সম্পূর্ণ করেছেন।"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"সাম্প্রতিক অ্যাপ দেখতে, নিজের টাচপ্যাডে তিনটি আঙুল ব্যবহার করে উপরের দিকে সোয়াইপ করে হোল্ড করুন"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"অ্যাপ পরিবর্তন করুন"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"অসাধারণ!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"আপনি অ্যাপ পরিবর্তন করার জেসচার সম্পূর্ণ করেছেন।"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"সব অ্যাপ দেখুন"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"আপনার কীবোর্ডে অ্যাকশন কী প্রেস করুন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 69f163512987..1b79810e67b4 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Vidžeti na zaključanom ekranu"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da otvorite aplikaciju pomoću vidžeta, morat ćete potvrditi identitet. Također imajte na umu da ih svako može pregledati, čak i ako je tablet zaključan. Neki vidžeti možda nisu namijenjeni za vaš zaključani ekran i njihovo dodavanje ovdje možda nije sigurno."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Razumijem"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidžeti"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Da dodate prečicu \"Vidžeti\", provjerite je li u postavkama omogućeno \"Prikazuj vidžete na zaključanom ekranu\"."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Postavke"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Dugme za prikaz čuvara ekrana"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Istraži način Huba"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Pristupite omiljenim widgetima i čuvarima zaslona tijekom punjenja."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Započnimo"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zamijeni korisnika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci iz ove sesije će se izbrisati."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ažuriranje"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Radni profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u avionu"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Roditeljski nadzor"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikazuje se na vrhu obavještenja u razgovorima i kao slika profila na zaključanom ekranu, izgleda kao oblačić, prekida funkciju Ne ometaj"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritetno"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava funkcije razgovora"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ta obavještenja se ne mogu izmijeniti."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Nije moguće izmijeniti obavještenja o pozivima."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ovu grupu obavještenja nije moguće konfigurirati ovdje"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mape"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne ometaj"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Prečica za dugmad za Jačinu zvuka"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Sistemske aplikacije"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Podijeljeni ekran"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Pristupačnost"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Unos"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Prečice aplikacije"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Trenutna aplikacija"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Izvršili ste pokret za prikaz nedavnih aplikacija."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Da pogledate nedavne aplikacije, prevucite nagore i zadržite s tri prsta na dodirnoj podlozi"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Promijenite aplikaciju"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Prijeđite udesno četirima prstima na dodirnoj podlozi"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Sjajno!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Izvršili ste pokret za promjenu aplikacije."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Prijeđite udesno četirima prstima na dodirnoj podlozi za prebacivanje između aplikacija"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Pogledajte sve aplikacije"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite tipku radnji na tastaturi"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Odlično!"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index d90c4fffd5aa..eae1b34f938c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets de la pantalla de bloqueig"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Per obrir una aplicació utilitzant un widget, necessitaràs verificar la teva identitat. També has de tenir en compte que qualsevol persona pot veure els widgets, fins i tot quan la tauleta està bloquejada. És possible que alguns widgets no estiguin pensats per a la pantalla de bloqueig i que no sigui segur afegir-los-hi."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entesos"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Per afegir la drecera Widgets, assegura\'t que l\'opció Mostra els widgets a la pantalla de bloqueig estigui activada a la configuració."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configuració"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botó Mostra l\'estalvi de pantalla"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Canvia d\'usuari"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"S\'està actualitzant"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de treball"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode d\'avió"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controls parentals"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> no sentiràs la pròxima alarma"</string>
<string name="alarm_template" msgid="2234991538018805736">"Hora: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"Dia: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Es mostra a la part superior de les notificacions de les converses i com a foto de perfil a la pantalla de bloqueig, apareix com una bombolla, interromp el mode No molestis"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritat"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admet les funcions de converses"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Aquestes notificacions no es poden modificar."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Les notificacions de trucades no es poden modificar."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Aquest grup de notificacions no es pot configurar aquí"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"No molestis"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Drecera per als botons de volum"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplicacions del sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasca"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Pantalla dividida"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibilitat"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrada"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Dreceres d\'aplicacions"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aplicació actual"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Has completat el gest per veure les aplicacions recents."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Per veure les aplicacions recents, llisca cap amunt amb tres dits i mantén-los premuts al ratolí tàctil"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Canviar d\'aplicació"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Ben fet!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Has completat el gest per canviar d\'aplicació."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Mostra totes les aplicacions"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Prem la tecla d\'acció al teclat"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2cfc4dab8e48..9422804b427b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgety na obrazovce uzamčení"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"K otevření aplikace pomocí widgetu budete muset ověřit svou totožnost. Také mějte na paměti, že widgety uvidí kdokoli, i když tablet bude uzamčen. Některé widgety nemusí být pro obrazovku uzamčení určeny a nemusí být bezpečné je na ni přidat."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Rozumím"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgety"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Pokud chcete přidat zkratku Widgety, zapněte v nastavení možnost Zobrazovat widgety na obrazovce uzamčení."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Nastavení"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Zobrazit tlačítko spořiče obrazovky"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Prozkoumejte Režim centra"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Mějte po ruce oblíbené widgety a spořiče obrazovky při nabíjení."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Jdeme na to"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Přepnout uživatele"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbalovací nabídka"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
@@ -802,6 +802,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny a deaktivuje režim Nerušit"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritní"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> funkce konverzace nepodporuje"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Tato oznámení nelze upravit."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornění na hovor nelze upravit."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Tuto skupinu oznámení tady nelze nakonfigurovat"</string>
@@ -912,6 +916,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendář"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulačka"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapy"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Nerušit"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Zkratka tlačítek hlasitosti"</string>
<string name="battery" msgid="769686279459897127">"Baterie"</string>
@@ -1497,12 +1511,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Provedli jste gesto pro zobrazení nedávných aplikací."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Pokud chcete zobrazit poslední aplikace, přejeďte na touchpadu třemi prsty nahoru a podržte je"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Přepnout aplikace"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Přejeďte po touchpadu čtyřmi prsty vpravo"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Výborně!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Dokončili jste gesto přepínání aplikací."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Přejetím čtyřmi prsty po touchpadu doprava přepněte aplikace"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Zobrazit všechny aplikace"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Stiskněte akční klávesu na klávesnici"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Výborně!"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 29961e340408..cb70b9a9dd67 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets på låseskærmen"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Hvis du vil åbne en app ved hjælp af en widget, skal du verificere din identitet. Husk også, at alle kan se dem, også når din tablet er låst. Nogle widgets er muligvis ikke beregnet til låseskærmen, og det kan være usikkert at tilføje dem her."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Hvis du vil tilføje genvejen \"Widgets\", skal du sørge for, at \"Vis widgets på låseskærmen\" er aktiveret i indstillingerne."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Indstillinger"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Knappen Vis pauseskærm"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skift bruger"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullemenu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps og data i denne session slettes."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Opdaterer"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Børnesikring"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"på <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Vises øverst i samtalenotifikationer og som et profilbillede på låseskærmen. Vises som en boble, der afbryder Forstyr ikke"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> understøtter ikke samtalefunktioner"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Disse notifikationer kan ikke redigeres."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Opkaldsnotifikationer kan ikke redigeres."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Du kan ikke konfigurere denne gruppe notifikationer her"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Lomme­regner"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Forstyr ikke"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Genvej til lydstyrkeknapper"</string>
<string name="battery" msgid="769686279459897127">"Batteri"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Systemapps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Opdelt skærm"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Hjælpefunktioner"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Appgenveje"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aktuel app"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du har udført bevægelsen for at se de seneste apps."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Du kan se nyligt brugte apps ved at stryge opad og holde tre fingre nede på touchpladen"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Skift mellem apps"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Godt klaret!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Du har fuldført bevægelsen for at skifte mellem apps."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Se alle apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tryk på handlingstasten på dit tastatur"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 2e452dda0f34..09c7067c301d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Sperrbildschirm-Widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Wenn du eine App mit einem Widget öffnen möchtest, musst du deine Identität bestätigen. Beachte auch, dass jeder die Widgets sehen kann, auch wenn dein Tablet gesperrt ist. Einige Widgets sind möglicherweise nicht für den Sperrbildschirm vorgesehen, sodass es unsicher sein kann, sie hier hinzuzufügen."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ok"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Zum Hinzufügen der Verknüpfung „Widgets“ musst du zuerst in den Einstellungen die Option „Widgets auf Sperrbildschirm zeigen“ aktivieren."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Einstellungen"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Schaltfläche „Bildschirmschoner anzeigen“"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Pull-down-Menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Wird aktualisiert…"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Arbeitsprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flugmodus"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Jugendschutzeinstellungen"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Lautloser Weckruf <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"um <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"am <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wird oben im Bereich „Unterhaltungen“ sowie als Profilbild auf dem Sperrbildschirm angezeigt, erscheint als Bubble, unterbricht „Bitte nicht stören“"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorität"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> unterstützt keine Funktionen für Unterhaltungen"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Diese Benachrichtigungen können nicht geändert werden."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Anrufbenachrichtigungen können nicht geändert werden."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Die Benachrichtigungsgruppe kann hier nicht konfiguriert werden"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Rechner"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Bitte nicht stören"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Tastenkombination für Lautstärketasten"</string>
<string name="battery" msgid="769686279459897127">"Akku"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"System-Apps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Splitscreen"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Bedienungshilfen"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Eingabe"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Tastaturkürzel für Apps"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aktuelle App"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du hast das Tutorial für die Touch-Geste zum Aufrufen der zuletzt verwendeten Apps abgeschlossen."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Wenn du zuletzt verwendete Apps aufrufen möchtest, wische mit drei Fingern nach oben und halte das Touchpad gedrückt"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Zwischen Apps wechseln"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Gut gemacht!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Du hast die Touch-Geste „Zwischen Apps wechseln\" abgeschlossen."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Alle Apps anzeigen"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Drücke die Aktionstaste auf deiner Tastatur"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index c5aa667e9c74..cc4ce17737ec 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Γραφικά στοιχεία οθόνης κλειδώματος"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Για να ανοίξετε μια εφαρμογή χρησιμοποιώντας ένα γραφικό στοιχείο, θα πρέπει να επαληθεύσετε την ταυτότητά σας. Επίσης, λάβετε υπόψη ότι η προβολή τους είναι δυνατή από οποιονδήποτε, ακόμα και όταν το tablet σας είναι κλειδωμένο. Ορισμένα γραφικά στοιχεία μπορεί να μην προορίζονται για την οθόνη κλειδώματος και η προσθήκη τους εδώ ενδέχεται να μην είναι ασφαλής."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Το κατάλαβα"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Για να προσθέσετε τη συντόμευση Γραφικά στοιχεία, βεβαιωθείτε ότι η ρύθμιση Εμφάνιση γραφικών στοιχείων στην οθόνη κλειδώματος είναι ενεργοποιημένη στις ρυθμίσεις."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ρυθμίσεις"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Εμφάνιση κουμπιού προφύλαξης οθόνης"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Εξερεύνηση της λειτουργίας Hub"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Αποκτήστε πρόσβαση στα αγαπημένα σας γραφικά στοιχεία και τις προφυλάξεις οθόνης κατά τη φόρτιση."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Ας ξεκινήσουμε"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Εναλλαγή χρήστη"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"αναπτυσσόμενο μενού"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Όλες οι εφαρμογές και τα δεδομένα αυτής της περιόδου σύνδεσης θα διαγραφούν."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ενημέρωση"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Προφίλ εργασίας"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Λειτουργία πτήσης"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Γονικοί έλεγχοι"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Δεν θα ακούσετε το επόμενο ξυπνητήρι σας <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"στις <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"στις <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Εμφανίζεται στην κορυφή των ειδοποιήσεων συζήτησης και ως φωτογραφία προφίλ στην οθόνη κλειδώματος, εμφανίζεται ως συννεφάκι, διακόπτει τη λειτουργία Μην ενοχλείτε"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Προτεραιότητα"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν υποστηρίζει τις λειτουργίες συζήτησης"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Δεν είναι δυνατή η τροποποίηση αυτών των ειδοποιήσεων"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Δεν είναι δυνατή η τροποποίηση των ειδοποιήσεων κλήσεων."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Δεν είναι δυνατή η διαμόρφωση αυτής της ομάδας ειδοποιήσεων εδώ"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Ημερολόγιο"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Αριθμομηχανή"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Χάρτες"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Μην ενοχλείτε"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Συντόμευση κουμπιών έντασης ήχου"</string>
<string name="battery" msgid="769686279459897127">"Μπαταρία"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Εφαρμογές συστήματος"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Πολυδιεργασία"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Διαχωρισμός οθόνης"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Προσβασιμότητα"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Εισαγωγή"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Συντομεύσεις εφαρμογών"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Τρέχουσα εφαρμογή"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ολοκληρώσατε την κίνηση για την προβολή πρόσφατων εφαρμογών."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Για προβολή πρόσφατων εφαρμογών, σύρετε προς τα επάνω με τρία δάχτυλα και κρατήστε τα δάχτυλά σας στην επιφάνεια αφής"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Εναλλαγή μεταξύ εφαρμογών"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Σύρετε προς τα δεξιά με τέσσερα δάχτυλα στην επιφάνεια αφής"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Μπράβο!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Ολοκληρώσατε την κίνηση εναλλαγής εφαρμογών."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Σύρετε προς τα δεξιά με τέσσερα δάχτυλα στην επιφάνεια αφής για εναλλαγή μεταξύ εφαρμογών"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Προβολή όλων των εφαρμογών"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Πατήστε το πλήκτρο ενέργειας στο πληκτρολόγιό σας"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Μπράβο!"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 4144dc300a58..c7ee5c5156d2 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"To add the \'Widgets\' shortcut, make sure that \'Show widgets on lock screen\' is enabled in settings."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Settings"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Show screensaver button"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Updating"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Parental controls"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"at <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"System apps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Split screen"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibility"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"App shortcuts"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Current app"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"To view recent apps, swipe up and hold using three fingers on your touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Switch apps"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Well done!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"You completed the switch apps gesture."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index b00b01d373f3..c26bee1e5c91 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you’ll need to verify it’s you. Also, keep in mind that anyone can view them, even when your tablet’s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"To add the \"Widgets\" shortcut, make sure \"Show widgets on lock screen\" is enabled in settings."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Settings"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Show screensaver button"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Explore hub mode"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Access your favorite widgets and screen savers while charging."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Let’s go"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -801,6 +801,8 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
+ <string name="notification_inline_dismiss" msgid="88423586921134258">"Dismiss"</string>
+ <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Don\'t show again"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -911,6 +913,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -1431,8 +1443,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"System apps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Split screen"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibility"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"App shortcuts"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Current App"</string>
@@ -1496,10 +1507,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"To view recent apps, swipe up and hold using three fingers on your touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Switch apps"</string>
- <string name="touchpad_switch_apps_gesture_guidance" msgid="2751565200937541667">"Swipe left using four fingers on your touchpad"</string>
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Swipe right using four fingers on your touchpad"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Great job!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"You completed the switch apps gesture."</string>
- <string name="touchpad_switch_gesture_error_body" msgid="5508381152326379652">"Swipe left using four fingers on your touchpad to switch apps"</string>
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Swipe right using four fingers on your touchpad to switch apps"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Well done!"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 4144dc300a58..c7ee5c5156d2 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"To add the \'Widgets\' shortcut, make sure that \'Show widgets on lock screen\' is enabled in settings."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Settings"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Show screensaver button"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Updating"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Parental controls"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"at <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"System apps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Split screen"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibility"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"App shortcuts"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Current app"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"To view recent apps, swipe up and hold using three fingers on your touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Switch apps"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Well done!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"You completed the switch apps gesture."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 4144dc300a58..c7ee5c5156d2 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lock screen widgets"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"To open an app using a widget, you\'ll need to verify that it\'s you. Also, bear in mind that anyone can view them, even when your tablet\'s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Got it"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"To add the \'Widgets\' shortcut, make sure that \'Show widgets on lock screen\' is enabled in settings."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Settings"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Show screensaver button"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Updating"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Parental controls"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"at <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"System apps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Split screen"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibility"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"App shortcuts"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Current app"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"To view recent apps, swipe up and hold using three fingers on your touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Switch apps"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Well done!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"You completed the switch apps gesture."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 85ff751d28ec..95ebbb25ff66 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets en la pantalla de bloqueo"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir una app usando un widget, debes verificar tu identidad. Además, ten en cuenta que cualquier persona podrá verlo, incluso cuando la tablet esté bloqueada. Es posible que algunos widgets no se hayan diseñados para la pantalla de bloqueo y podría ser peligroso agregarlos allí."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para agregar el acceso directo de \"Widgets\", asegúrate de que la opción \"Mostrar widgets en la pantalla de bloqueo\" esté habilitada en la configuración."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configuración"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botón para mostrar el protector de pantalla"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú expandible"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Actualizando"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avión"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controles parentales"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma a la(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"a la(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"el <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparece en forma de burbuja y como foto de perfil en la parte superior de las notificaciones de conversación, en la pantalla de bloqueo, y detiene el modo No interrumpir"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritaria"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite funciones de conversación"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"No se pueden modificar estas notificaciones."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"No se pueden modificar las notificaciones de llamada."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"No se puede configurar aquí este grupo de notificaciones"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendario"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"No interrumpir"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Combinación de teclas de botones de volumen"</string>
<string name="battery" msgid="769686279459897127">"Batería"</string>
@@ -1432,14 +1448,13 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Apps del sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Tareas múltiples"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Pantalla dividida"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accesibilidad"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrada"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Accesos directos a aplicaciones"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"App actual"</string>
<string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accesibilidad"</string>
<string name="shortcut_helper_title" msgid="8567500639300970049">"Combinaciones de teclas"</string>
- <string name="shortcut_helper_customize_mode_title" msgid="8327297960035006036">"Personalizar combinaciones de teclas"</string>
+ <string name="shortcut_helper_customize_mode_title" msgid="8327297960035006036">"Personalizar combinaciones"</string>
<string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"¿Quieres quitar la combinación?"</string>
<string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"¿Quieres restablecer la configuración predeterminada?"</string>
<string name="shortcut_customize_mode_add_shortcut_description" msgid="7636040209946696120">"Para crear esta combinación de teclas, presiona la tecla de acción y una o más teclas"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Completaste el gesto para ver las apps recientes."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Para ver las apps recientes, desliza tres dedos hacia arriba y mantenlos presionados en el panel táctil"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Cambia de app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"¡Bien hecho!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Completaste el gesto para cambiar de app."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas las apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Presiona la tecla de acción en el teclado"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 62c629074ce1..2c88f8ead989 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets para la pantalla de bloqueo"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir una aplicación usando un widget, deberás verificar que eres tú. Además, ten en cuenta que cualquier persona podrá verlos, incluso aunque tu tablet esté bloqueada. Es posible que algunos widgets no estén pensados para la pantalla de bloqueo y no sea seguro añadirlos aquí."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para añadir el acceso directo Widgets, asegúrate de que la opción Mostrar widgets en la pantalla de bloqueo esté habilitada en los ajustes."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ajustes"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botón para mostrar el salvapantallas"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar de usuario"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Actualizando"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo Avión"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controles parentales"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
<string name="alarm_template" msgid="2234991538018805736">"a las <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Se muestra encima de las notificaciones de conversaciones y como imagen de perfil en la pantalla de bloqueo, aparece como burbuja e interrumpe el modo No molestar"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite funciones de conversación"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Estas notificaciones no se pueden modificar."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Las notificaciones de llamada no se pueden modificar."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Este grupo de notificaciones no se puede configurar aquí"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendario"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"No molestar"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Acceso directo de los botones de volumen"</string>
<string name="battery" msgid="769686279459897127">"Batería"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplicaciones del sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitarea"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Pantalla dividida"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accesibilidad"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrada"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Accesos directos a aplicaciones"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aplicación en uso"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Has completado el gesto para ver las aplicaciones recientes."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Para ver las aplicaciones recientes, desliza tres dedos hacia arriba y mantén pulsado en el panel táctil"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Cambiar de aplicación"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"¡Bien hecho!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Has completado el gesto para cambiar de aplicación."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas las aplicaciones"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pulsa la tecla de acción de tu teclado"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 920af5c4d353..c96cc0473bb6 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lukustuskuva vidinad"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Rakenduse avamiseks vidina abil peate kinnitama, et see olete teie. Samuti pidage meeles, et kõik saavad vidinaid vaadata, isegi kui teie tahvelarvuti on lukus. Mõni vidin ei pruugi olla ette nähtud teie lukustuskuva jaoks ja seda pole turvaline siia lisada."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Selge"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidinad"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Otsetee „Vidinad“ lisamiseks veenduge, et seadetes oleks valik „Kuva lukustuskuval vidinad“ lubatud."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Seaded"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Nupp Kuva ekraanisäästja"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kasutaja vahetamine"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rippmenüü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Värskendamine"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Tööprofiil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lennukirežiim"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Vanemlik järelevalve"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Te ei kuule järgmist äratust kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Kuvatakse mullina vestluste märguannete ülaosas ja profiilipildina lukustuskuval ning katkestab režiimi Mitte segada"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioriteetne"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei toeta vestlusfunktsioone"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Neid märguandeid ei saa muuta."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Kõnemärguandeid ei saa muuta."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Seda märguannete rühma ei saa siin seadistada"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulaator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Mitte segada"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Helitugevuse nuppude otsetee"</string>
<string name="battery" msgid="769686279459897127">"Aku"</string>
@@ -1273,7 +1289,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"Sisu kuvatakse peagi"</string>
<string name="missed_call" msgid="4228016077700161689">"Vastamata kõne"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"Vaadake hiljutisi sõnumeid, vastamata kõnesid ja olekuvärskendusi"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"Vaadake hiljutisi sõnumeid, vastamata kõnesid ja olekuvärskendusi."</string>
<string name="people_tile_title" msgid="6589377493334871272">"Vestlus"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Peatas režiim Mitte segada"</string>
<string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> saatis sõnumi: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Süsteemirakendused"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitegumtöö"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Jagatud ekraanikuva"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Juurdepääsetavus"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Sisend"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Rakenduse otseteed"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Praegune rakendus"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Tegite hiljutiste rakenduste vaatamise liigutuse."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Hiljutiste rakenduste kuvamiseks pühkige puuteplaadil kolme sõrmega üles ja hoidke sõrmi puuteplaadil"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Rakenduste vahetamine"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Väga hea!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Tegite rakenduste vahetamise liigutuse."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Kõigi rakenduste kuvamine"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Vajutage klaviatuuril toiminguklahvi"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 912da58efc44..b8643a287d57 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Pantaila blokeatuko widgetak"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Aplikazio bat widget baten bidez irekitzeko, zeu zarela egiaztatu beharko duzu. Gainera, kontuan izan edonork ikusi ahalko dituela halako widgetak, tableta blokeatuta badago ere. Baliteke widget batzuk pantaila blokeaturako egokiak ez izatea, eta agian ez da segurua haiek bertan gehitzea."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ados"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgetak"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Widgetak\" lasterbidea gehitzeko, ziurtatu \"Erakutsi widgetak pantaila blokeatuan\" gaituta dagoela ezarpenetan."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ezarpenak"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Erakutsi pantaila-babeslearen botoia"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Aldatu erabiltzailea"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"zabaldu menua"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Saioko aplikazio eta datu guztiak ezabatuko dira."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Eguneratzen"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Laneko profila"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Hegaldi modua"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Guraso-murriztapenak"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ez duzu entzungo hurrengo alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
<string name="alarm_template" msgid="2234991538018805736">"ordua: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"data: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Elkarrizketen jakinarazpenen goialdean eta profileko argazki gisa agertzen da pantaila blokeatuan, burbuila batean, eta ez molestatzeko modua eteten du"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Lehentasuna"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez ditu onartzen elkarrizketetarako eginbideak"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Jakinarazpen horiek ezin dira aldatu."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Deien jakinarazpenak ezin dira aldatu."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Jakinarazpen talde hau ezin da konfiguratu hemen"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulagailua"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ez molestatzeko modua"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Bolumen-botoietarako lasterbidea"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -1432,14 +1448,13 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Sistemaren aplikazioak"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Zeregin bat baino gehiago aldi berean exekutatzea"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Pantaila zatitzea"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Erabilerraztasuna"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Sarrera"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Aplikazioetarako lasterbideak"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Oraingo aplikazioa"</string>
<string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Erabilerraztasuna"</string>
<string name="shortcut_helper_title" msgid="8567500639300970049">"Lasterbideak"</string>
- <string name="shortcut_helper_customize_mode_title" msgid="8327297960035006036">"Pertsonalizatu lasterbideak"</string>
+ <string name="shortcut_helper_customize_mode_title" msgid="8327297960035006036">"Pertsonalizatu"</string>
<string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Lasterbidea kendu nahi duzu?"</string>
<string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Balio lehenetsia berrezarri nahi duzu?"</string>
<string name="shortcut_customize_mode_add_shortcut_description" msgid="7636040209946696120">"Lasterbide hau sortzeko, sakatu ekintza-tekla eta beste tekla bat edo gehiago batera"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Osatu duzu azkenaldiko aplikazioak ikusteko keinua."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Azkenaldiko aplikazioak ikusteko, pasatu 3 hatz gora eta eduki sakatuta ukipen-panelean"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Aldatu aplikazioa"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bikain!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Ikasi duzu aplikazio batetik bestera aldatzeko keinua."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ikusi aplikazio guztiak"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Sakatu teklatuko ekintza-tekla"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 3612b16de761..2a3c3c02762f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ابزاره‌های صفحه قفل"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"برای باز کردن برنامه بااستفاده از ابزاره، باید هویت خودتان را به‌تأیید برسانید. همچنین، به‌خاطر داشته باشید که همه می‌توانند آن‌ها را مشاهده کنند، حتی وقتی رایانه لوحی‌تان قفل است. برخی‌از ابزاره‌ها ممکن است برای صفحه قفل درنظر گرفته نشده باشند و ممکن است اضافه کردن آن‌ها در اینجا ناامن باشد."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"متوجهم"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ابزاره‌ها"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"برای افزودن میان‌بر «ابزاره‌ها»، مطمئن شوید «نمایش ابزاره‌ها در صفحه قفل» در تنظیمات فعال باشد."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"تنظیمات"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"دکمه نمایش دادن محافظ صفحه‌نمایش"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"کاوش کردن حالت متصل"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"در حین شارژ، به ابزاره‌ها و محافظ‌های صفحه‌نمایش دلخواهتان دسترسی داشته باشید."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"بیایید شروع کنیم"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تغییر کاربر"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"منوی پایین‌پر"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامه‌ها و داده‌های این جلسه حذف خواهد شد."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"درحال به‌روزرسانی"</string>
<string name="status_bar_work" msgid="5238641949837091056">"نمایه کاری"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"حالت هواپیما"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"کنترل‌های والدین"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"در ساعت <xliff:g id="WHEN">%1$s</xliff:g>، دیگر صدای زنگ ساعت را نمی‌شنوید"</string>
<string name="alarm_template" msgid="2234991538018805736">"در <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"در <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"در بالای اعلان‌های مکالمه و به‌صورت عکس نمایه در صفحه قفل نشان داده می‌شود، به‌صورت حبابک ظاهر می‌شود، در حالت «مزاحم نشوید» وقفه ایجاد می‌کند"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"اولویت"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ویژگی‌های مکالمه پشتیبانی نمی‌کند"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"این اعلان‌ها قابل اصلاح نیستند."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"این اعلان‌ها قابل‌اصلاح نیستند."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"نمی‌توانید این گروه اعلان‌ها را در اینجا پیکربندی کنید"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"تقویم"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ماشین‌حساب"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"مزاحم نشوید"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"میان‌بر دکمه‌های صدا"</string>
<string name="battery" msgid="769686279459897127">"باتری"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"برنامه‌های سیستم"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"چندوظیفگی"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"صفحهٔ دونیمه"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"دسترس‌پذیری"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ورودی"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"میان‌برهای برنامه"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"برنامه فعلی"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"اشاره «مشاهده برنامه‌های اخیر» را تمام کردید"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"برای مشاهده برنامه‌های اخیر، با سه انگشت روی صفحه لمسی تند به‌بالا بکشید و نگه دارید"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"جابه‌جایی بین برنامه‌ها"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"با چهار انگشت روی صفحه لمسی تند به چپ بکشید"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"عالی است!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"اشاره جابه‌جایی بین برنامه‌ها را تکمیل کردید."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"برای جابه‌جا شدن بین برنامه‌ها، با چهار انگشت روی صفحه لمسی تند به چپ بکشید"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"مشاهده همه برنامه‌ها"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"دکمه کنش را روی صفحه لمسی فشار دهید"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"عالی بود!"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9f1c72306b22..67e0c283563f 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -537,10 +537,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Lukitusnäytön widgetit"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Jos haluat avata sovelluksen käyttämällä widgetiä, sinun täytyy vahvistaa henkilöllisyytesi. Muista myös, että widgetit näkyvät kaikille, vaikka tabletti olisi lukittuna. Jotkin widgetit on ehkä tarkoitettu lukitusnäytölle, ja niiden lisääminen tänne ei välttämättä ole turvallista."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Selvä"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgetit"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Jos haluat lisätä Widgetit-pikakuvakkeen, varmista, että \"Näytä widgetit lukitusnäytöllä\" on käytössä asetuksissa."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Asetukset"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Näytä näytönsäästäjän painike"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Vaihda käyttäjää"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"alasvetovalikko"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Kaikki sovellukset ja tämän istunnon tiedot poistetaan."</string>
@@ -752,8 +755,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Päivitetään"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Työprofiili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lentokonetila"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Lapsilukko"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Et kuule seuraavaa hälytystäsi (<xliff:g id="WHEN">%1$s</xliff:g>)."</string>
<string name="alarm_template" msgid="2234991538018805736">"kello <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"ajankohtana <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -804,6 +806,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Näkyy keskusteluilmoitusten yläosassa ja profiilikuvana lukitusnäytöllä, näkyy kuplana, keskeyttää Älä häiritse ‑tilan"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Tärkeä"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei tue keskusteluominaisuuksia"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Näitä ilmoituksia ei voi muokata"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Puheluilmoituksia ei voi muokata."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Tätä ilmoitusryhmää ei voi määrittää tässä"</string>
@@ -914,6 +920,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalenteri"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Laskin"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Älä häiritse"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Äänenvoimakkuuspainikkeiden pikanäppäin"</string>
<string name="battery" msgid="769686279459897127">"Akku"</string>
@@ -1434,8 +1450,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Järjestelmäsovellukset"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitaskaus"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Jaettu näyttö"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Saavutettavuus"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Syöte"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Sovellusten pikakuvakkeet"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Nykyinen sovellus"</string>
@@ -1499,11 +1514,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Olet oppinut Katso viimeisimmät sovellukset ‑eleen."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Näet äskeiset sovellukset, kun pyyhkäiset ylös ja pidät kosketuslevyä painettuna kolmella sormella."</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Vaihda sovellusta"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Hienoa!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Olet oppinut sovelluksenvaihtoeleen."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Näytä kaikki sovellukset"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Paina näppäimistön toimintonäppäintä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6bcce5300d38..5d0c67bafcb0 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets de l\'écran de verrouillage"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pour ouvrir une appli à l\'aide d\'un widget, vous devrez confirmer votre identité. En outre, gardez à l\'esprit que tout le monde peut voir les widgets, même lorsque votre tablette est verrouillée. Certains widgets n\'ont peut-être pas été conçus pour votre écran de verrouillage, et il pourrait être dangereux de les ajouter ici."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Pour ajouter le raccourci « Widgets », assurez-vous que « Afficher les widgets sur l\'écran de verrouillage » est activé dans les paramètres."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Paramètres"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Afficher le bouton de l\'écran de veille"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Explorer le mode Console"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Accéder à vos widgets et écrans de veille préférés pendant le chargement."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Allons-y"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applis et les données de cette session seront supprimées."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mise à jour en cours…"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Contrôles parentaux"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"le <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"S\'affiche dans le haut des notifications de conversation et comme photo de profil à l\'écran de verrouillage, s\'affiche comme bulle, interrompt le mode Ne pas déranger"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne prend pas en charge les fonctionnalités de conversation"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ces notifications ne peuvent pas être modifiées"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Les notifications d\'appel ne peuvent pas être modifiées."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ce groupe de notifications ne peut pas être configuré ici"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculatrice"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Raccourci des boutons de volume"</string>
<string name="battery" msgid="769686279459897127">"Pile"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Applis système"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitâche"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Écran divisé"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibilité"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrée"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Raccourcis des applis"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Appli actuelle"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Vous avez effectué le geste pour afficher les applis récentes."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Pour afficher vos applis récentes, balayez votre pavé tactile vers le haut avec trois doigts et maintenez-les en place"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Changer d\'appli"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Balayez votre pavé tactile vers la droite avec quatre doigts"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bon travail!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Vous avez terminé le geste de changement d\'appli."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Balayez votre pavé tactile vers la droite avec quatre doigts pour changer d\'appli"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Afficher toutes les applis"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Appuyez sur la touche d\'action de votre clavier"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Félicitations!"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 33628260ff49..389957633c55 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets pour l\'écran de verrouillage"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pour ouvrir une appli à l\'aide d\'un widget, vous devez confirmer qu\'il s\'agit bien de vous. N\'oubliez pas non plus que tout le monde peut voir vos widgets, même lorsque votre tablette est verrouillée. Certains d\'entre eux n\'ont pas été conçus pour l\'écran de verrouillage et les ajouter à cet endroit peut s\'avérer dangereux."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Pour ajouter le raccourci \"Widgets\", assurez-vous que l\'option \"Afficher les widgets sur l\'écran de verrouillage\" est activée dans les paramètres."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Paramètres"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Afficher le bouton \"Économiseur d\'écran\""</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Découvrir le mode Hub"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Accédez à vos widgets et économiseurs d\'écran préférés lorsque l\'appareil est en charge."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"C\'est parti"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mise à jour"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Contrôle parental"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>."</string>
<string name="alarm_template" msgid="2234991538018805736">"à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"le <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,8 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"S\'affiche en haut des notifications de conversation et en tant que photo de profil sur l\'écran de verrouillage, apparaît sous forme de bulle, interrompt le mode Ne pas déranger"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas compatible avec les fonctionnalités de conversation"</string>
+ <string name="notification_inline_dismiss" msgid="88423586921134258">"Ignorer"</string>
+ <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Ne plus afficher"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Impossible de modifier ces notifications."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Impossible de modifier les notifications d\'appel."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Vous ne pouvez pas configurer ce groupe de notifications ici"</string>
@@ -912,6 +913,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculatrice"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Raccourci des boutons de volume"</string>
<string name="battery" msgid="769686279459897127">"Batterie"</string>
@@ -1432,8 +1443,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Applis système"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitâche"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Écran partagé"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibilité"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Saisie"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Raccourcis d\'application"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Appli actuelle"</string>
@@ -1497,12 +1507,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Vous avez appris le geste pour afficher les applis récentes"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Pour afficher les applis récentes, balayez le pavé tactile vers le haut avec trois doigts et maintenez la position"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Passer d\'une application à l\'autre"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Balayez vers la droite avec quatre doigts sur le pavé tactile"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bravo !"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Vous avez appris le geste pour passer d\'une appli à l\'autre."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Balayez vers la droite avec quatre doigts sur le pavé tactile pour passer d\'une appli à une autre"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Afficher toutes les applications"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Appuyez sur la touche d\'action de votre clavier"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Bravo !"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 60fe0b098d01..56323279fd6c 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da pantalla de bloqueo"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir unha aplicación mediante un widget, tes que verificar a túa identidade. Ten en conta que pode velos calquera persoa, mesmo coa tableta bloqueada. Pode ser que algúns widgets non estean pensados para a túa pantalla de bloqueo, polo que talvez non sexa seguro engadilos aquí."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendido"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para engadir o atallo Widgets, vai a Configuración e comproba que está activada a opción Mostrar widgets na pantalla de bloqueo."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configuración"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botón para mostrar o protector de pantalla"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú despregable"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Eliminaranse todas as aplicacións e datos desta sesión."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Actualizando"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de traballo"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controis parentais"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"ás <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Móstrase na parte superior das notificacións das conversas e como imaxe do perfil na pantalla de bloqueo, aparece como unha burbulla e interrompe o modo Non molestar"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non admite funcións de conversa"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Estas notificacións non se poden modificar."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"As notificacións de chamadas non se poden modificar."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Aquí non se pode configurar este grupo de notificacións"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Non molestar"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atallo dos botóns de volume"</string>
<string name="battery" msgid="769686279459897127">"Batería"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplicacións do sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitarefa"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Pantalla dividida"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accesibilidade"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrada"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Atallos de aplicacións"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aplicación actual"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Completaches o titorial do xesto de consultar aplicacións recentes."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Para ver as aplicacións recentes, pasa tres dedos cara arriba e mantenos premidos no panel táctil"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Cambiar de aplicación"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bravo!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Completaches o xesto para cambiar de aplicación."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas as aplicacións"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Preme a tecla de acción do teclado"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index f9c5b81a615d..5c4142397bfb 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"લૉક સ્ક્રીન વિજેટ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"વિજેટનો ઉપયોગ કરીને ઍપ ખોલવા માટે, તમારે એ ચકાસણી કરવાની જરૂર રહેશે કે આ તમે જ છો. તે ઉપરાંત, ધ્યાનમાં રાખો કે તમારું ટૅબ્લેટ લૉક કરેલું હોય તો પણ કોઈપણ વ્યક્તિ તેમને જોઈ શકે છે. અમુક વિજેટ કદાચ તમારી લૉક સ્ક્રીન માટે બનાવવામાં આવ્યા ન હોઈ શકે છે અને તેમને અહીં ઉમેરવાનું અસલામત હોઈ શકે છે."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"સમજાઈ ગયું"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"વિજેટ"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"વિજેટ\"નો શૉર્ટકટ ઉમેરવા માટે, ખાતરી કરો કે સેટિંગમાં \"લૉક સ્ક્રીન પર વિજેટ બતાવો\" સુવિધા ચાલુ કરેલી છે."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"સેટિંગ"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"સ્ક્રીનસેવર બટન બતાવો"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"વપરાશકર્તા સ્વિચ કરો"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"પુલડાઉન મેનૂ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"આ સત્રમાંની તમામ ઍપ અને ડેટા કાઢી નાખવામાં આવશે."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"અપડેટ કરી રહ્યાં છીએ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ઑફિસની પ્રોફાઇલ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"એરપ્લેન મોડ"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"માતાપિતાના યોગ્ય નિયંત્રણો"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"તમે <xliff:g id="WHEN">%1$s</xliff:g> એ તમારો આગલો એલાર્મ સાંભળશો નહીં"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> વાગ્યે"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> એ"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"વાતચીતના નોટિફિકેશન વિભાગની ટોચ પર અને લૉક કરેલી સ્ક્રીન પર પ્રોફાઇલ ફોટો તરીકે બતાવે છે, બબલ તરીકે દેખાય છે, ખલેલ પાડશો નહીં મોડમાં વિક્ષેપ ઊભો કરે છે"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"પ્રાધાન્યતા"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> વાતચીતની સુવિધાઓને સપોર્ટ આપતી નથી"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"આ નોટિફિકેશનમાં કોઈ ફેરફાર થઈ શકશે નહીં."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"કૉલના નોટિફિકેશનમાં કોઈ ફેરફાર કરી શકાતો નથી."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"નોટિફિકેશનના આ ગ્રૂપની ગોઠવણી અહીં કરી શકાશે નહીં"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"કેલ્ક્યુલેટર"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ખલેલ પાડશો નહીં"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"વૉલ્યૂમ બટન્સ શૉર્ટકટ"</string>
<string name="battery" msgid="769686279459897127">"બૅટરી"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"સિસ્ટમ ઍપ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"એકથી વધુ કાર્યો કરવા"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"સ્ક્રીનને વિભાજિત કરો"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ઍક્સેસિબિલિટી"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ઇનપુટ"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ઍપ શૉર્ટકટ"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"હાલની ઍપ"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"તમે \'તાજેતરની ઍપ જુઓ\' સંકેત પૂર્ણ કર્યો."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"તાજેતરની ઍપ જોવા માટે, તમારા ટચપૅડ પર ત્રણ આંગળી વડે ઉપરની તરફ સ્વાઇપ કરો અને દબાવી રાખો"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ઍપ સ્વિચ કરો"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"ખૂબ સરસ કામ!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"તમે ઍપ સ્વિચ કરવાનો સંકેત પૂર્ણ કર્યો છે."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"બધી ઍપ જુઓ"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"તમારા કીબોર્ડ પરની ઍક્શન કી દબાવો"</string>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index 8c8d5f649407..17b47cc201d0 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -193,7 +193,7 @@
</string-array>
<string-array name="tile_states_notes">
<item msgid="5894333929299989301">"અનુપલબ્ધ"</item>
- <item msgid="6419996398343291862">"બંધ"</item>
+ <item msgid="6419996398343291862">"બંધ છે"</item>
<item msgid="5908720590832378783">"ચાલુ"</item>
</string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index efb080ab0204..221327ce2c3f 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"लॉक स्क्रीन विजेट"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"किसी विजेट से कोई ऐप्लिकेशन खोलने के लिए, आपको अपनी पहचान की पुष्टि करनी होगी. ध्यान रखें कि आपके टैबलेट के लॉक होने पर भी, कोई व्यक्ति विजेट देख सकता है. ऐसा हो सकता है कि कुछ विजेट, लॉक स्क्रीन पर दिखाने के लिए न बने हों. इन्हें लॉक स्क्रीन पर जोड़ना असुरक्षित हो सकता है."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ठीक है"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"विजेट"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"विजेट\" शॉर्टकट जोड़ने के लिए, पक्का करें कि सेटिंग में \"लॉक स्क्रीन पर विजेट दिखाएं\" चालू हो."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"सेटिंग"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"स्क्रीन सेवर दिखाने का बटन"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"उपयोगकर्ता बदलें"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेन्यू"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सेशन के सभी ऐप्लिकेशन और डेटा को हटा दिया जाएगा."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"अपडेट हो रहा है"</string>
<string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"फ़्लाइट मोड"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"माता-पिता के कंट्रोल"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म नहीं सुनाई देगा"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> बजे"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> पर"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"यह कई तरीकों से दिखती है, जैसे कि बातचीत वाली सूचनाओं में सबसे ऊपर, बबल के तौर पर, और लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर. साथ ही, यह \'परेशान न करें\' मोड को बायपास कर सकती है"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर बातचीत की सुविधाएं काम नहीं करतीं"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ये सूचनाएं नहीं बदली जा सकती हैं."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कॉल से जुड़ी सूचनाओं को ब्लॉक नहीं किया जा सकता."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"सूचनाओं के इस समूह को यहां कॉन्फ़िगर नहीं किया जा सकता"</string>
@@ -878,8 +884,8 @@
<string name="group_system_go_back" msgid="2730322046244918816">"वापस जाने के लिए"</string>
<string name="group_system_access_home_screen" msgid="4130366993484706483">"होम स्क्रीन पर जाने के लिए"</string>
<string name="group_system_overview_open_apps" msgid="5659958952937994104">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने के लिए"</string>
- <string name="group_system_cycle_forward" msgid="5478663965957647805">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन के अगले पेज पर जाने के लिए"</string>
- <string name="group_system_cycle_back" msgid="8194102916946802902">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन के पिछले पेज पर जाने के लिए"</string>
+ <string name="group_system_cycle_forward" msgid="5478663965957647805">"हाल में इस्तेमाल किए गए ऐप्लिकेशन पर, सीधे क्रम में वापस जाने के लिए"</string>
+ <string name="group_system_cycle_back" msgid="8194102916946802902">"हाल में इस्तेमाल किए गए ऐप्लिकेशन पर, उलटे क्रम में वापस जाने के लिए"</string>
<string name="group_system_access_all_apps_search" msgid="1553588630154197469">"ऐप्लिकेशन की सूची खोलने के लिए"</string>
<string name="group_system_access_system_settings" msgid="8731721963449070017">"सेटिंग खोलने के लिए"</string>
<string name="group_system_access_google_assistant" msgid="7210074957915968110">"सहायक ऐप्लिकेशन खोलने के लिए"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"कैलकुलेटर"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"मैप"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"परेशान न करें"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"वॉल्यूम बटन का शॉर्टकट"</string>
<string name="battery" msgid="769686279459897127">"बैटरी"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"सिस्टम के ऐप्लिकेशन"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"मल्टीटास्किंग (एक साथ कई काम करना)"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"स्प्लिट स्क्रीन"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"सुलभता"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"इनपुट"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ऐप शॉर्टकट"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"मौजूदा ऐप्लिकेशन"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"अब आपको हाथ के जेस्चर का इस्तेमाल करके, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने का तरीका पता चल गया है."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने के लिए, अपने टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करें और दबाकर रखें"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ऐप्लिकेशन के बीच स्विच करें"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"बहुत बढ़िया!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"आपने जान लिया है कि हाथ का जेस्चर इस्तेमाल करके ऐप्लिकेशन के बीच स्विच कैसे करें."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"सभी ऐप्लिकेशन देखें"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"अपने कीबोर्ड पर ऐक्शन बटन दबाएं"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 5078bfffeff9..60b39a4bf539 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgeti na zaključanom zaslonu"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Da biste otvorili aplikaciju pomoću widgeta, trebate potvrditi da ste to vi. Također napominjemo da ih svatko može vidjeti, čak i ako je vaš tablet zaključan. Neki widgeti možda nisu namijenjeni za zaključani zaslon, pa ih možda nije sigurno dodati ovdje."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Shvaćam"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgeti"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Da biste dodali prečac Widgeti, provjerite je li u postavkama omogućena opcija Prikaži widgete na zaključanom zaslonu."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Postavke"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Prikaži gumb čuvara zaslona"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Istraži način Huba"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Pristupite omiljenim widgetima i čuvarima zaslona tijekom punjenja."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Započnimo"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Promjena korisnika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući izbornik"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Izbrisat će se sve aplikacije i podaci u ovoj sesiji."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ažuriranje"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u zrakoplovu"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Roditeljski nadzor"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikazuje se pri vrhu obavijesti razgovora i kao profilna slika na zaključanom zaslonu, izgleda kao oblačić, prekida Ne uznemiravaj"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritetno"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava značajke razgovora"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Te se obavijesti ne mogu izmijeniti."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obavijesti o pozivima ne mogu se izmijeniti."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ta se grupa obavijesti ne može konfigurirati ovdje"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Karte"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne uznemiravaj"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Prečac tipki za glasnoću"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplikacije sustava"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Obavljanje više zadataka"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Podijeljeni zaslon"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Pristupačnost"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Unos"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Prečaci aplikacija"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Trenutačna aplikacija"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Napravili ste pokret za prikaz nedavno korištenih aplikacija."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Za prikaz nedavnih aplikacija prijeđite trima prstima prema gore na dodirnoj podlozi i zadržite pritisak"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Promjena aplikacije"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Prijeđite udesno četirima prstima na dodirnoj podlozi"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Sjajno!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Izvršili ste pokret za promjenu aplikacije."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Prijeđite udesno četirima prstima na dodirnoj podlozi za prebacivanje između aplikacija"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Prikaži sve aplikacije"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite tipku za radnju na tipkovnici"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Izvrsno!"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index cce273260779..568c8725158b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"A lezárási képernyő moduljai"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ha modul használatával szeretne megnyitni egy alkalmazást, igazolnia kell a személyazonosságát. Ne felejtse továbbá, hogy bárki megtekintheti a modulokat, még akkor is, amikor zárolva van a táblagép. Előfordulhat, hogy bizonyos modulokat nem a lezárási képernyőn való használatra terveztek, ezért nem biztonságos a hozzáadásuk."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Értem"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Modulok"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"A „Modulok” gyorsparancs hozzáadásához gondoskodjon arról, hogy a „Modulok megjelenítése a lezárási képernyőn” beállítás legyen engedélyezve a beállításokban."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Beállítások"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Képernyőkímélő gomb megjelenítése"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"A Hub mód felfedezése"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Töltés közben hozzáférhet kedvenc moduljaihoz és képernyőkímélőihez."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Kezdés"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Felhasználóváltás"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"lehúzható menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Frissítés…"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Munkahelyi profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Repülős üzemmód"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Szülői felügyelet"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nem fogja hallani az ébresztést ekkor: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"ekkor: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"ezen a napon: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"A beszélgetésekre vonatkozó értesítések tetején, lebegő buborékként látható, megjeleníti a profilképet a lezárási képernyőn, és megszakítja a Ne zavarjanak funkciót"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritás"</string>
<string name="no_shortcut" msgid="8257177117568230126">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> nem támogatja a beszélgetési funkciókat"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ezeket az értesítéseket nem lehet módosítani."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"A hívásértesítéseket nem lehet módosítani."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Az értesítések jelen csoportját itt nem lehet beállítani"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Naptár"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Számológép"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Térkép"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne zavarjanak"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"A hangerőgombok gyorsbillentyűk"</string>
<string name="battery" msgid="769686279459897127">"Akkumulátor"</string>
@@ -1432,14 +1445,13 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Rendszeralkalmazások"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Osztott képernyő"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Kisegítő lehetőségek"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Bevitel"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Alkalmazásikonok"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Jelenlegi alkalmazás"</string>
<string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Kisegítő lehetőségek"</string>
<string name="shortcut_helper_title" msgid="8567500639300970049">"Billentyűparancsok"</string>
- <string name="shortcut_helper_customize_mode_title" msgid="8327297960035006036">"Gyorsparancsok személyre szabása"</string>
+ <string name="shortcut_helper_customize_mode_title" msgid="8327297960035006036">"Billentyűparancsok"</string>
<string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Eltávolítja a billentyűparancsot?"</string>
<string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Visszaállítja az alapértelmezett beállításokat?"</string>
<string name="shortcut_customize_mode_add_shortcut_description" msgid="7636040209946696120">"A billentyűparancs létrehozásához nyomja le egyszerre a műveletbillentyűt és egy vagy több másik billentyűt"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Teljesítette a legutóbbi alkalmazások megtekintésének kézmozdulatát."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"A legutóbbi appokért csúsztasson gyorsan három ujjal felfelé az érintőpadon, és tartsa lenyomva ujjait."</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Váltás az alkalmazások között"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Csúsztasson gyorsan négy ujjal jobbra az érintőpadon"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Kiváló!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Teljesítette az appváltó gesztust."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Az alkalmazások közötti váltáshoz csúsztasson gyorsan négy ujjal jobbra az érintőpadon"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Összes alkalmazás megtekintése"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Nyomja meg a műveletbillentyűt az érintőpadon."</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Szép munka!"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 10cf6703e3e0..60b445ff0eab 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Կողպէկրանի վիջեթներ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Վիջեթի միջոցով հավելված բացելու համար դուք պետք է հաստատեք ձեր ինքնությունը։ Նաև նկատի ունեցեք, որ ցանկացած ոք կարող է դիտել վիջեթները, նույնիսկ երբ ձեր պլանշետը կողպված է։ Որոշ վիջեթներ կարող են նախատեսված չլինել ձեր կողպէկրանի համար, և այստեղ դրանց ավելացնելը կարող է վտանգավոր լինել։"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Եղավ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Վիջեթներ"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"«Վիջեթներ» դյուրանցումն ավելացնելու համար համոզվեք, որ «Ցույց տալ վիջեթները կողպէկրանին» պարամետրը միացված է կարգավորումներում։"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Կարգավորումներ"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"«Ցույց տալ էկրանապահը» կոճակ"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Անջատել օգտվողին"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"իջնող ընտրացանկ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Թարմացում"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Android for Work-ի պրոֆիլ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Ավիառեժիմ"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Ծնողական վերահսկողություն"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>-ին"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>-ին"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Ցուցադրվում է զրույցների ծանուցումների վերևում, ինչպես նաև կողպէկրանին որպես պրոֆիլի նկար, հայտնվում է ամպիկի տեսքով, ընդհատում է «Չանհանգստացնել» ռեժիմը"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Կարևոր"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը զրույցի գործառույթներ չի աջակցում"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Այս ծանուցումները չեն կարող փոփոխվել:"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Զանգերի մասին ծանուցումները հնարավոր չէ փոփոխել։"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ծանուցումների տվյալ խումբը հնարավոր չէ կարգավորել այստեղ"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Օրացույց"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Հաշվիչ"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Քարտեզներ"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Չանհանգստացնել"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Ձայնի կոճակների դյուրանցում"</string>
<string name="battery" msgid="769686279459897127">"Մարտկոց"</string>
@@ -1497,11 +1513,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Դուք կատարեցիք վերջին օգտագործված հավելվածների դիտման ժեստը։"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Վերջին հավելվածները տեսնելու համար երեք մատը սահեցրեք վերև և սեղմած պահեք հպահարթակին"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Անցում մեկ հավելվածից մյուսին"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Կեցցե՛ք։"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Դուք սովորեցիք ուրիշ հավելված անցնելու ժեստը։"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ինչպես դիտել բոլոր հավելվածները"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string>
@@ -1511,7 +1527,7 @@
<string name="tutorial_animation_content_description" msgid="2698816574982370184">"Ուղեցույցի անիմացիա․ սեղմեք՝ նվագարկումը դադարեցնելու/վերսկսելու համար։"</string>
<string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Հետին լուսավորությամբ ստեղնաշար"</string>
<string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d՝ %2$d-ից"</string>
- <string name="home_controls_dream_label" msgid="6567105701292324257">"Տան կառավարման տարրեր"</string>
+ <string name="home_controls_dream_label" msgid="6567105701292324257">"Տան կառավարում"</string>
<string name="home_controls_dream_description" msgid="4644150952104035789">"Տան կառավարման տարրերը դարձրեք էկրանապահ"</string>
<string name="volume_undo_action" msgid="5815519725211877114">"Հետարկել"</string>
<string name="back_edu_toast_content" msgid="4530314597378982956">"Հետ գնալու համար երեք մատը հպահարթակի վրա սահեցրեք ձախ կամ աջ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a5f01997654a..0a6baca254b4 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget layar kunci"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Untuk membuka aplikasi menggunakan widget, Anda perlu memverifikasi diri Anda. Selain itu, harap ingat bahwa siapa saja dapat melihatnya, bahkan saat tablet Anda terkunci. Beberapa widget mungkin tidak dirancang untuk layar kunci Anda dan mungkin tidak aman untuk ditambahkan di sini."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Oke"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widget"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Untuk menambahkan pintasan \"Widget\", pastikan \"Tampilkan widget di layar kunci\" diaktifkan di setelan."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Setelan"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Tampilkan tombol screensaver"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pulldown"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Update berlangsung"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Kontrol orang tua"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"pukul <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Muncul teratas di notifikasi percakapan dan sebagai foto profil di layar kunci, ditampilkan sebagai balon, menimpa mode Jangan Ganggu"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritas"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak mendukung fitur percakapan"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Notifikasi ini tidak dapat diubah."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Notifikasi panggilan tidak dapat diubah."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Grup notifikasi ini tidak dapat dikonfigurasi di sini"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Jangan Ganggu"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Pintasan tombol volume"</string>
<string name="battery" msgid="769686279459897127">"Baterai"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplikasi sistem"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Layar terpisah"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Aksesibilitas"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Pintasan aplikasi"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aplikasi Saat Ini"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Anda telah menyelesaikan gestur untuk melihat aplikasi terbaru."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Untuk melihat aplikasi terbaru, geser ke atas dan tahan menggunakan tiga jari di touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Beralih aplikasi"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bagus!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Anda telah menyelesaikan gestur beralih aplikasi."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Lihat semua aplikasi"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tekan tombol tindakan di keyboard"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 576a22742573..46c8452374e7 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Græjur fyrir lásskjá"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Þú þarft að staðfesta að þetta sért þú til að geta opnað forrit með græju. Hafðu einnig í huga að hver sem er getur skoðað þær, jafnvel þótt spjaldtölvan sé læst. Sumar græjur eru hugsanlega ekki ætlaðar fyrir lásskjá og því gæti verið óöruggt að bæta þeim við hér."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ég skil"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Græjur"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Gakktu úr skugga um að kveikt sé á „Sýna græjur á lásskjá“ til að geta bætt flýtileiðinni „Græjur“ við."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Stillingar"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Hnappurinn „Sýna skjávara“"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skipta um notanda"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Fellivalmynd"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Uppfærir"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Vinnusnið"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flugstilling"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Barnalæsing"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ekki mun heyrast í vekjaranum <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Birtist efst í samtalstilkynningum og sem prófílmynd á lásskjánum. Birtist sem blaðra sem truflar „Ónáðið ekki“"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Forgangur"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> styður ekki samtalseiginleika"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ekki er hægt að breyta þessum tilkynningum."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Ekki er hægt að breyta tilkynningum um símtöl."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ekki er hægt að stilla þessar tilkynningar hér"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Dagatal"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Reiknivél"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Kort"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ónáðið ekki"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Flýtihnappar fyrir hljóðstyrk"</string>
<string name="battery" msgid="769686279459897127">"Rafhlaða"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Kerfisforrit"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Fjölvinnsla"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Skjáskipting"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Aðgengi"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Innsláttur"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Flýtileiðir forrita"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Núverandi forrit"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Þú framkvæmdir bendinguna til að sjá nýleg forrit."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Strjúktu upp og haltu þremur fingrum inni á snertifletinum til að sjá nýleg forrit"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Að skipta á milli forrita"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Vel gert!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Þú framkvæmdir bendinguna til að skipta á milli forrita."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Sjá öll forrit"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Ýttu á aðgerðalykilinn á lyklaborðinu"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 9b847c4c344d..30ad41f6fc5a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget della schermata di blocco"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Per aprire un\'app utilizzando un widget, dovrai verificare la tua identità. Inoltre tieni presente che chiunque può vederlo, anche quando il tablet è bloccato. Alcuni widget potrebbero non essere stati progettati per la schermata di blocco e potrebbe non essere sicuro aggiungerli qui."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ok"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widget"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Per aggiungere la scorciatoia \"Widget\", assicurati che l\'opzione \"Mostra widget sulla schermata di blocco\" sia abilitata nelle impostazioni."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Impostazioni"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Pulsante Mostra salvaschermo"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambio utente"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu a discesa"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Aggiornamento in corso…"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profilo di lavoro"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modalità aereo"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controllo genitori"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Non sentirai la tua prossima sveglia <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"alle <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Appare in cima alle notifiche delle conversazioni, come immagine del profilo nella schermata di blocco e sotto forma di bolla, inoltre interrompe la modalità Non disturbare"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non supporta le funzionalità delle conversazioni"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Impossibile modificare queste notifiche."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Impossibile modificare gli avvisi di chiamata."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Qui non è possibile configurare questo gruppo di notifiche"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendario"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calcolatrice"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Non disturbare"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Pulsanti del volume come scorciatoia"</string>
<string name="battery" msgid="769686279459897127">"Batteria"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"App di sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Schermo diviso"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibilità"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Scorciatoie app"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"App corrente"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Hai completato il gesto Visualizza app recenti."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Per visualizzare le app recenti, scorri verso l\'alto e tieni premuto con tre dita sul touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Cambia app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Ottimo lavoro."</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Hai completato il gesto Cambia app."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Visualizza tutte le app"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Premi il tasto azione sulla tastiera"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index afa1af584c44..df5614815789 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -225,7 +225,7 @@
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"הפעולה הזו נדרשת כדי לשפר את האבטחה והביצועים"</string>
<string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"הגדרה חוזרת של \'ביטול הנעילה בטביעת אצבע\'"</string>
<string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"פתיחה בטביעת אצבע"</string>
- <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"הגדרת \'ביטול הנעילה בטביעת אצבע\'"</string>
+ <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"הגדרת \"פתיחה בטביעת אצבע\""</string>
<string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"כדי להגדיר שוב את התכונה \'ביטול הנעילה בטביעת אצבע\', עליך למחוק את התבניות והמודלים הנוכחיים של טביעת האצבע.\n\nאחרי המחיקה יהיה צורך להגדיר שוב את \'ביטול הנעילה בטביעת אצבע\' כדי להשתמש בטביעת האצבע לביטול הנעילה של הטלפון ולאמת את זהותך."</string>
<string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"כדי להגדיר שוב את התכונה \'ביטול הנעילה בטביעת אצבע\', עליך למחוק את התבניות והמודל הנוכחיים של טביעת האצבע.\n\nאחרי המחיקה יהיה צורך להגדיר שוב את \'ביטול הנעילה בטביעת אצבע\' כדי להשתמש בטביעת האצבע לביטול הנעילה של הטלפון ולאמת את זהותך."</string>
<string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"לא ניתן להגדיר ביטול נעילה בטביעת אצבע. יש לעבור להגדרות כדי לנסות שוב."</string>
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ווידג\'טים במסך הנעילה"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"כדי לפתוח אפליקציה באמצעות ווידג\'ט, עליך לאמת את זהותך. בנוסף, כדאי לזכור שכל אחד יכול לראות את הווידג\'טים גם כשהטאבלט שלך נעול. יכול להיות שחלק מהווידג\'טים לא נועדו למסך הנעילה ושלא בטוח להוסיף אותם לכאן."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"הבנתי"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ווידג\'טים"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"כדי להוסיף את קיצור הדרך \"ווידג\'טים\", צריך לוודא שהאפשרות \"ווידג\'טים במסך הנעילה\" מופעלת בהגדרות."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"הגדרות"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"כפתור להצגת שומר המסך"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"החלפת משתמש"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"תפריט במשיכה למטה"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"כל האפליקציות והנתונים בסשן הזה יימחקו."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"מתבצע עדכון"</string>
<string name="status_bar_work" msgid="5238641949837091056">"פרופיל עבודה"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"מצב טיסה"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"אמצעי בקרת הורים"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"לא ניתן יהיה לשמוע את השעון המעורר הבא שלך <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"בשעה <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"ב-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"מוצגת בחלק העליון של קטע התראות השיחה וכתמונת פרופיל במסך הנעילה, מופיעה בבועה צפה ומפריעה במצב \'נא לא להפריע\'"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"בעדיפות גבוהה"</string>
<string name="no_shortcut" msgid="8257177117568230126">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא תומכת בתכונות השיחה"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"לא ניתן לשנות את ההתראות האלה."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"לא ניתן לשנות את התראות השיחה."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"לא ניתן להגדיר כאן את קבוצת ההתראות הזו"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"יומן"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"מחשבון"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"מפות"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"נא לא להפריע"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"קיצור דרך לכפתורי עוצמת קול"</string>
<string name="battery" msgid="769686279459897127">"סוללה"</string>
@@ -1428,12 +1444,11 @@
<string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"בשימוש על ידי <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
<string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"נעשה שימוש לאחרונה על ידי <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
<string name="shortcut_helper_category_system" msgid="462110876978937359">"מערכת"</string>
- <string name="shortcut_helper_category_system_controls" msgid="3153344561395751020">"הגדרות המערכת"</string>
+ <string name="shortcut_helper_category_system_controls" msgid="3153344561395751020">"שליטה במערכת"</string>
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"אפליקציות מערכת"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ריבוי משימות"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"מסך מפוצל"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"נגישות"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"קלט"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"מקשי קיצור לאפליקציות"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"האפליקציה הנוכחית"</string>
@@ -1478,8 +1493,7 @@
<string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"חזרה"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"חזרה לדף הבית"</string>
<string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"הצגת האפליקציות האחרונות"</string>
- <!-- no translation found for touchpad_tutorial_switch_apps_gesture_button (7768255095423767779) -->
- <skip />
+ <string name="touchpad_tutorial_switch_apps_gesture_button" msgid="7768255095423767779">"מעבר בין אפליקציות"</string>
<string name="touchpad_tutorial_done_button" msgid="176168488821755503">"סיום"</string>
<string name="gesture_error_title" msgid="469064941635578511">"צריך לנסות שוב."</string>
<string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"חזרה"</string>
@@ -1497,15 +1511,12 @@
<string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"מעולה!"</string>
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"סיימת לתרגל את התנועה להצגת האפליקציות האחרונות."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"כדי לראות את האפליקציות האחרונות, צריך להחליק למעלה וללחוץ לחיצה ארוכה עם שלוש אצבעות על לוח המגע"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_action_title (6835222344612924512) -->
- <skip />
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
- <!-- no translation found for touchpad_switch_apps_gesture_success_title (4894947244328032458) -->
- <skip />
- <!-- no translation found for touchpad_switch_apps_gesture_success_body (8151089866035126312) -->
+ <string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"מעבר בין אפליקציות"</string>
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"מעולה!"</string>
+ <string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"השלמת את תנועת המעבר בין האפליקציות."</string>
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"צפייה בכל האפליקציות"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"צריך להקיש על מקש הפעולה במקלדת"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 87c6aedfd4a0..d58859045a17 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ロック画面ウィジェット"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ウィジェットを使用してアプリを起動するには、本人確認が必要です。タブレットがロックされた状態でも他のユーザーにウィジェットが表示されますので、注意してください。一部のウィジェットについてはロック画面での使用を想定していないため、ロック画面への追加は危険な場合があります。"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ウィジェット"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"[ウィジェット] ショートカットを追加するには、設定で [ロック画面でのウィジェットの表示] が有効になっていることを確認してください。"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"設定"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"スクリーンセーバー表示ボタン"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"ハブモードの詳細を見る"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"充電中にお気に入りのウィジェットやスクリーン セーバーにアクセスできます。"</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"使ってみる"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ユーザーを切り替える"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"プルダウン メニュー"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"更新しています"</string>
<string name="status_bar_work" msgid="5238641949837091056">"仕事用プロファイル"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"機内モード"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"保護者による使用制限"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"次回のアラーム(<xliff:g id="WHEN">%1$s</xliff:g>)は鳴りません"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"会話通知の一番上に表示されると同時に、ロック画面にプロフィール写真として表示されるほか、バブルとして表示され、サイレント モードが中断されます"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>は会話機能に対応していません"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"これらの通知は変更できません。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"着信通知は変更できません。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"このグループの通知はここでは設定できません"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"カレンダー"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"電卓"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"マップ"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"サイレント モード"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量ボタンのショートカット"</string>
<string name="battery" msgid="769686279459897127">"バッテリー"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"システムアプリ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"マルチタスク"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"分割画面"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ユーザー補助"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"入力"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"アプリのショートカット"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"現在のアプリ"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"「最近使ったアプリを表示する」ジェスチャーを学習しました。"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"最近使ったアプリを表示するには、3 本の指でタッチパッドを上にスワイプして長押しします"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"アプリの切り替え"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"タッチパッドを 4 本の指で右にスワイプします"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"よくできました!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"アプリを切り替えるジェスチャーを学習しました。"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"アプリを切り替えるには、タッチパッドを 4 本の指で右にスワイプします"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"すべてのアプリを表示"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"キーボードのアクションキーを押します"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"完了です!"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 31f486f05373..1a2d2be67b66 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"დაბლოკილი ეკრანის ვიჯეტები"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"უნდა დაადასტუროთ თქვენი ვინაობა, რათა გახსნათ აპი ვიჯეტის გამოყენებით. გაითვალისწინეთ, რომ ნებისმიერს შეუძლია მათი ნახვა, მაშინაც კი, როცა ტაბლეტი დაბლოკილია. ზოგი ვიჯეტი შეიძლება არ იყოს გათვლილი თქვენი დაბლოკილი ეკრანისთვის და მათი აქ დამატება შეიძლება სახიფათო იყოს."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"გასაგებია"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ვიჯეტები"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"„ვიჯეტების“ მალსახმობის დასამატებლად დარწმუნდით, რომ პარამეტრებში ჩართულია „დაბლოკილ ეკრანზე ვიჯეტების ჩვენება“."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"პარამეტრები"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"ეკრანმზოგის ღილაკის ჩვენება"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"ჰაბის რეჟიმის დათვალიერება"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"დატენის დროს შეგიძლიათ თქვენს რჩეულ ვიჯეტებზე და ეკრანმზოგებზე წვდომა."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"დავიწყოთ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"მომხმარებლის გადართვა"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ჩამოშლადი მენიუ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ამ სესიის ყველა აპი და მონაცემი წაიშლება."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"მიმდინარეობს განახლება"</string>
<string name="status_bar_work" msgid="5238641949837091056">"სამსახურის პროფილი"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"თვითმფრინავის რეჟიმი"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"მშობელთა კონტროლი"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ვერ გაიგონებთ მომდევნო მაღვიძარას <xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"გამოჩნდება საუბრის შეტყობინებების თავში და პროფილის სურათის სახით ჩაკეტილ ეკრანზე, ჩნდება ბუშტის სახით, წყვეტს ფუნქციას „არ შემაწუხოთ“"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"პრიორიტეტი"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ს არ აქვს მიმოწერის ფუნქციების მხარდაჭერა"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ამ შეტყობინებების შეცვლა შეუძლებელია."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ზარის შეტყობინებების შეცვლა შეუძლებელია."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"შეტყობინებების ამ ჯგუფის კონფიგურირება აქ შეუძლებელია"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"კალენდარი"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"კალკულატორი"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"არ შემაწუხოთ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ხმის ღილაკების მალსახმობი"</string>
<string name="battery" msgid="769686279459897127">"ბატარეა"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"სისტემის აპები"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"მრავალამოცანიანი რეჟიმი"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"ეკრანის გაყოფა"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"მარტივი წვდომა"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"შეყვანა"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"აპის მალსახმობები"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"მიმდინარე აპი"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"თქვენ დაასრულეთ ბოლო აპების ხედის ჟესტი."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ბოლო აპების სანახავად თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზევით და ხანგრძლივად დააჭირეთ"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"აპების გადართვა"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"თქვენს სენსორულ პანელზე ოთხი თითით გადაფურცლეთ მარჯვნივ"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"შესანიშნავია!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"თქვენ შეასრულეთ აპების გადართვის ჟესტი."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"აპების გადასართავად თქვენს სენსორულ პანელზე ოთხი თითით გადაფურცლეთ მარჯვნივ"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"ყველა აპის ნახვა"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ყოჩაღ!"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 0b6c7b9919b2..54fb72a70182 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Құлып экранының виджеттері"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Қолданбаны виджет көмегімен ашу үшін жеке басыңызды растауыңыз керек. Сондай-ақ басқалар оларды планшетіңіз құлыптаулы кезде де көре алатынын ескеріңіз. Кейбір виджеттер құлып экранына арналмаған болады, сондықтан оларды мұнда қосу қауіпсіз болмауы мүмкін."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Түсінікті"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджеттер"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Виджеттер\" таңбашасын қосу үшін параметрлерде \"Виджеттерді құлыптаулы экранда көрсету\" опциясының қосулы екенін тексеріңіз."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Параметрлер"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Скринсейвер түймесін көрсету"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Пайдаланушыны ауыстыру"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ашылмалы мәзір"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданба мен дерек жойылады."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Жаңартылып жатыр"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Ата-ана бақылауы"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Келесі <xliff:g id="WHEN">%1$s</xliff:g> дабылыңызды есітпейсіз"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Әңгіме туралы хабарландырулардың жоғарғы жағында тұрады және құлыптаулы экранда профиль суреті болып көрсетіледі, қалқыма хабар түрінде шығады, Мазаламау режимін тоқтатады."</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Маңызды"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> әңгіме функцияларын қолдамайды."</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Бұл хабарландыруларды өзгерту мүмкін емес."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Қоңырау туралы хабарландыруларды өзгерту мүмкін емес."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Мұндай хабарландырулар бұл жерде конфигурацияланбайды."</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Күнтізбе"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Мазаламау"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Дыбыс деңгейі түймелерінің төте жолы"</string>
<string name="battery" msgid="769686279459897127">"Батарея"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Жүйелік қолданбалар"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Мультитаскинг"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Экранды бөлу"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Арнайы мүмкіндіктер"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Енгізу"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Қолданба таңбашалары"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Қолданыстағы қолданба"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Соңғы қолданбаларды көру қимылын орындадыңыз."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Соңғы қолданбаларды көру үшін сенсорлық тақтада үш саусақпен жоғары сырғытып, ұстап тұрыңыз."</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Қолданба ауыстыру"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Жарайсыз!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Қолданба ауыстыру қимылын аяқтадыңыз."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Барлық қолданбаны көру"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Пернетақтадағы әрекет пернесін басыңыз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index a2f5b01c81de..e827fc7989ab 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ធាតុ​ក្រាហ្វិកលើអេក្រង់ចាក់សោ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ដើម្បីបើកកម្មវិធីដោយប្រើធាតុ​ក្រាហ្វិក អ្នកនឹងត្រូវផ្ទៀងផ្ទាត់ថាជាអ្នក។ ទន្ទឹមនឹងនេះ សូមចងចាំថា នរណាក៏អាចមើលធាតុក្រាហ្វិកបាន សូម្បីពេលថេប្លេតរបស់អ្នកជាប់សោក៏ដោយ។ ធាតុ​ក្រាហ្វិកមួយចំនួនប្រហែលមិនត្រូវបានរចនាឡើងសម្រាប់អេក្រង់ចាក់សោរបស់អ្នកទេ និងមិនមានសុវត្ថិភាពឡើយ បើបញ្ចូលទៅទីនេះ។"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"យល់ហើយ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ធាតុ​ក្រាហ្វិក"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"ដើម្បីបញ្ចូលផ្លូវកាត់ \"ធាតុ​ក្រាហ្វិក\" ត្រូវប្រាកដថា \"បង្ហាញធាតុ​ក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ\" ត្រូវបានបើកនៅក្នុងការកំណត់។"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ការកំណត់"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"បង្ហាញប៊ូតុងធាតុ​រក្សា​អេក្រង់"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរ​អ្នក​ប្រើ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ម៉ឺនុយ​ទាញចុះ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យ​ទាំងអស់​ក្នុង​វគ្គ​នេះ​នឹង​ត្រូវ​លុប។"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"កំពុងដំឡើង​កំណែ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"កម្រងព័ត៌មានការងារ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ពេលជិះយន្តហោះ"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"ការគ្រប់គ្រង​ដោយ​មាតាបិតា"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"អ្នកនឹងមិនលឺម៉ោងរោទ៍ <xliff:g id="WHEN">%1$s</xliff:g> បន្ទាប់របស់អ្នកទេ"</string>
<string name="alarm_template" msgid="2234991538018805736">"នៅ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"នៅ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"បង្ហាញនៅខាងលើ​ការជូនដំណឹងអំពីការសន្ទនា និងជារូបភាព​កម្រង​ព័ត៌មាននៅលើអេក្រង់ចាក់សោ បង្ហាញជាពពុះ បង្អាក់មុខងារកុំ​រំខាន"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"អាទិភាព"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> មិនអាចប្រើ​មុខងារ​សន្ទនា​បានទេ"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"មិនអាច​កែប្រែ​ការជូនដំណឹង​ទាំងនេះ​បានទេ។"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"មិនអាច​កែប្រែ​ការជូនដំណឹងអំពីការហៅទូរសព្ទបានទេ។"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"មិនអាច​កំណត់​រចនាសម្ព័ន្ធ​ក្រុមការជូនដំណឹងនេះ​នៅទីនេះ​បានទេ"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ប្រតិទិន"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ម៉ាស៊ីនគិតលេខ"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ផែនទី"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"កុំ​រំខាន"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ផ្លូវកាត់ប៊ូតុងកម្រិតសំឡេង"</string>
<string name="battery" msgid="769686279459897127">"ថ្ម"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"កម្មវិធី​ប្រព័ន្ធ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ការធ្វើកិច្ចការច្រើន"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"មុខងារ​បំបែកអេក្រង់"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ភាពងាយស្រួល"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"វិធីបញ្ចូល"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ផ្លូវកាត់​កម្មវិធី"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"កម្មវិធីបច្ចុប្បន្ន"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"អ្នកបានបញ្ចប់ការមើលចលនាកម្មវិធីថ្មីៗ។"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ដើម្បីមើលកម្មវិធីថ្មីៗ សូមអូសឡើងលើ រួចសង្កត់ឱ្យជាប់លើផ្ទាំងប៉ះរបស់អ្នក ដោយប្រើម្រាមដៃបី"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ប្ដូរ​កម្មវិធី"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"ធ្វើបានល្អ!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"អ្នក​បានបញ្ចប់​ចលនា​ប្ដូរកម្មវិធី​ហើយ។"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"មើល​កម្មវិធី​ទាំងអស់"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ចុចគ្រាប់ចុចសកម្មភាពលើក្ដារចុចរបស់អ្នក"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 76f38c0337db..bfc9d7506952 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ ವಿಜೆಟ್‌ಗಳು"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ವಿಜೆಟ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ಆ್ಯಪ್ ತೆರೆಯಲು, ಇದು ನೀವೇ ಎಂದು ನೀವು ದೃಢೀಕರಿಸಬೇಕಾಗುತ್ತದೆ. ಅಲ್ಲದೆ, ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಲಾಕ್ ಆಗಿದ್ದರೂ ಸಹ ಯಾರಾದರೂ ಅವುಗಳನ್ನು ವೀಕ್ಷಿಸಬಹುದು ಎಂಬುದನ್ನು ನೆನಪಿನಲ್ಲಿಡಿ. ಕೆಲವು ವಿಜೆಟ್‌ಗಳು ನಿಮ್ಮ ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ಗಾಗಿ ಉದ್ದೇಶಿಸದೇ ಇರಬಹುದು ಮತ್ತು ಇಲ್ಲಿ ಸೇರಿಸುವುದು ಸುರಕ್ಷಿತವಲ್ಲದಿರಬಹುದು."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ಅರ್ಥವಾಯಿತು"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ವಿಜೆಟ್‌ಗಳು"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"ವಿಜೆಟ್‌ಗಳು\" ಶಾರ್ಟ್‌ಕಟ್ ಸೇರಿಸಲು, ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ \"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ವಿಜೆಟ್‌ಗಳನ್ನು ತೋರಿಸಿ\" ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"ಸ್ಕ್ರೀನ್‌ಸೇವರ್ ಬಟನ್ ತೋರಿಸಿ"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"ಹಬ್ ಮೋಡ್ ಅನ್ನು ಎಕ್ಸ್‌ಪ್ಲೋರ್ ಮಾಡಿ"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"ಚಾರ್ಜ್ ಮಾಡುವಾಗ ನಿಮ್ಮ ನೆಚ್ಚಿನ ವಿಜೆಟ್‌ಗಳು ಮತ್ತು ಸ್ಕ್ರೀನ್ ಸೇವರ್‌ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"ಪ್ರಾರಂಭಿಸೋಣ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ಪುಲ್‌ಡೌನ್ ಮೆನು"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ಈ ಸೆಶನ್‌ನಲ್ಲಿನ ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"ಅಪ್‌ಡೇಟ್‌‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"ಪೋಷಕ ನಿಯಂತ್ರಣಗಳು"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ನಿಮ್ಮ ಮುಂದಿನ <xliff:g id="WHEN">%1$s</xliff:g> ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ರಲ್ಲಿ"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> ರಂದು"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ಸಂಭಾಷಣೆ ಅಧಿಸೂಚನೆಗಳ ಮೇಲ್ಭಾಗದಲ್ಲಿ ಹಾಗೂ ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನ ಮೇಲೆ ಪ್ರೊಫೈಲ್ ಚಿತ್ರವಾಗಿ ತೋರಿಸುತ್ತದೆ, ಬಬಲ್‌ನಂತೆ ಗೋಚರಿಸುತ್ತದೆ, ಅಡಚಣೆ ಮಾಡಬೇಡ ಮೋಡ್‌ಗೆ ಅಡ್ಡಿಯುಂಟುಮಾಡುತ್ತದೆ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ಆದ್ಯತೆ"</string>
<string name="no_shortcut" msgid="8257177117568230126">"ಸಂವಾದ ಫೀಚರ್‌ಗಳನ್ನು <xliff:g id="APP_NAME">%1$s</xliff:g> ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ಕರೆ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ಈ ಗುಂಪಿನ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇಲ್ಲಿ ಕಾನ್ಫಿಗರ್‌ ಮಾಡಲಾಗಿರುವುದಿಲ್ಲ"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ಕ್ಯಾಲ್ಕ್ಯುಲೇಟರ್"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳ ಶಾರ್ಟ್‌ಕಟ್‌"</string>
<string name="battery" msgid="769686279459897127">"ಬ್ಯಾಟರಿ"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"ಸಿಸ್ಟಂ ಆ್ಯಪ್‌ಗಳು"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ಮಲ್ಟಿಟಾಸ್ಕಿಂಗ್"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ಇನ್‌ಪುಟ್"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ಆ್ಯಪ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"ಪ್ರಸ್ತುತ ಆ್ಯಪ್"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ನೀವು ಇತ್ತೀಚಿನ ಆ್ಯಪ್‌ಗಳ ಜೆಸ್ಚರ್‌ ವೀಕ್ಷಣೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಲು, ನಿಮ್ಮ ಟಚ್‌ಪ್ಯಾಡ್‌ನಲ್ಲಿ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಹೋಲ್ಡ್ ಮಾಡಿ"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ಆ್ಯಪ್‌ಗಳನ್ನು ಬದಲಿಸಿ"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"ನಿಮ್ಮ ಟಚ್‌ಪ್ಯಾಡ್‌ನಲ್ಲಿ ನಾಲ್ಕು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"ಭೇಷ್!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"ನೀವು ಆ್ಯಪ್‌ಗಳನ್ನು ಬದಲಾಯಿಸುವ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"ಆ್ಯಪ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ನಿಮ್ಮ ಟಚ್‌ಪ್ಯಾಡ್‌ನಲ್ಲಿ ನಾಲ್ಕು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್‌ನಲ್ಲಿ ಆ್ಯಕ್ಷನ್‌ ಕೀಯನ್ನು ಒತ್ತಿ"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ಭೇಷ್!"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c087e5891229..b4e3c14c93a0 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"잠금 화면 위젯"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"위젯을 사용하여 앱을 열려면 본인 인증을 해야 합니다. 또한 태블릿이 잠겨 있더라도 누구나 볼 수 있다는 점을 유의해야 합니다. 일부 위젯은 잠금 화면에 적합하지 않고 여기에 추가하기에 안전하지 않을 수 있습니다."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"확인"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"위젯"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\'위젯\' 바로가기를 추가하려면 설정에서 \'잠금 화면에 위젯 표시\'가 사용 설정되어 있어야 합니다."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"설정"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"화면 보호기 버튼 표시"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"사용자 전환"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"풀다운 메뉴"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"업데이트 중"</string>
<string name="status_bar_work" msgid="5238641949837091056">"직장 프로필"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"비행기 모드"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"자녀 보호 기능"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
<string name="alarm_template" msgid="2234991538018805736">"시간: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"일시: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -761,7 +763,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"위성, 연결 상태 양호"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"위성, 연결 가능"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"위성 긴급 SOS"</string>
- <string name="satellite_emergency_only_carrier_text" msgid="9103913890116841786">"긴급 전화 또는 SOS만 허용"</string>
+ <string name="satellite_emergency_only_carrier_text" msgid="9103913890116841786">"긴급 전화 또는 SOS만"</string>
<string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
<string name="accessibility_no_signal" msgid="7052827511409250167">"신호가 없습니다"</string>
<string name="accessibility_one_bar" msgid="5342012847647834506">"신호 막대가 1개입니다"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"대화 알림 상단에 표시, 잠금 화면에 프로필 사진으로 표시, 대화창으로 표시, 방해 금지 모드를 무시함"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"우선순위"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱은 대화 기능을 지원하지 않습니다."</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"이 알림은 수정할 수 없습니다."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"전화 알림은 수정할 수 없습니다."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"이 알림 그룹은 여기에서 설정할 수 없습니다."</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"계산기"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"지도"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"방해 금지 모드"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"볼륨 버튼 단축키"</string>
<string name="battery" msgid="769686279459897127">"배터리"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"시스템 앱"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"멀티태스킹"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"화면 분할"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"접근성"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"입력"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"앱 단축키"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"현재 앱"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"최근 앱 보기 동작을 완료했습니다."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"최근 앱을 보려면 터치패드에서 세 손가락을 사용해 위로 스와이프한 채로 유지하세요."</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"앱 전환"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"잘하셨습니다"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"앱 전환 동작을 완료했습니다."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"모든 앱 보기"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"키보드의 작업 키를 누르세요."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 5d1b604fa152..a3e20a41675a 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Кулпуланган экрандагы виджеттер"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Колдонмону виджет аркылуу ачуу үчүн өзүңүздү ырасташыңыз керек. Алар кулпуланган планшетиңизде да көрүнүп турат. Кээ бир виджеттерди кулпуланган экранда колдоно албайсыз, андыктан аларды ал жерге кошпой эле койгонуңуз оң."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Түшүндүм"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджеттер"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Виджеттер\" ыкчам баскычын кошуу үчүн параметрлерге өтүп, \"Виджеттерди кулпуланган экранда көрсөтүү\" параметри иштетилгенин текшериңиз."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Параметрлер"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Көшөгө баскычын көрсөтүү"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Колдонуучуну которуу"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ылдый түшүүчү меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана аларга байланыштуу нерселер өчүрүлөт."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Жаңырууда"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Жумуш профили"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Учак режими"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Ата-эненин көзөмөлү"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки эскертмени укпайсыз"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> болгондо"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> болгондо"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Cүйлөшүүлөр тууралуу билдирмелердин жогору жагында жана кулпуланган экранда профилдин сүрөтү, ошондой эле калкып чыкма билдирме түрүндө көрүнүп, \"Тынчымды алба\" режимин токтотот"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Маанилүүлүгү"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда оозеки сүйлөшкөнгө болбойт"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Бул билдирмелерди өзгөртүүгө болбойт."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Чалуу билдирмелерин өзгөртүүгө болбойт."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Бул билдирмелердин тобун бул жерде конфигурациялоого болбойт"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Жылнаама"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Эсептегич"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карталар"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Тынчымды алба"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Үндү көзөмөлдөөчү баскычтардын кыска жолдору"</string>
<string name="battery" msgid="769686279459897127">"Батарея"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Системанын колдонмолору"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Бир нече тапшырма аткаруу"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Экранды бөлүү"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Атайын мүмкүнчүлүктөр"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Киргизүү"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Колдонмонун ыкчам баскычтары"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Учурдагы колдонмо"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Акыркы колдонмолорду көрүү жаңсоосун аткардыңыз."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Соңку колдонмолорду көрүү үчүн сенсордук тактаны үч манжаңыз менен жогору сүрүп, кармап туруңуз"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Колдонмолорду которуштуруу"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Азаматсыз!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"\"Башка колдонмого которулуу жаңсоосу боюнча үйрөткүчтү бүтүрдүңүз."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Бардык колдонмолорду көрүү"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Баскычтобуңуздагы аракет баскычын басыңыз"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 37713b32ac9d..eade9f17d175 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ວິດເຈັດໃນໜ້າຈໍລັອກ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ເພື່ອເປີດແອັບໂດຍໃຊ້ວິດເຈັດ, ທ່ານຈະຕ້ອງຢັ້ງຢືນວ່າແມ່ນທ່ານ. ນອກຈາກນັ້ນ, ກະລຸນາຮັບຊາບວ່າທຸກຄົນສາມາດເບິ່ງຂໍ້ມູນດັ່ງກ່າວໄດ້, ເຖິງແມ່ນວ່າແທັບເລັດຂອງທ່ານຈະລັອກຢູ່ກໍຕາມ. ວິດເຈັດບາງຢ່າງອາດບໍ່ໄດ້ມີໄວ້ສຳລັບໜ້າຈໍລັອກຂອງທ່ານ ແລະ ອາດບໍ່ປອດໄພທີ່ຈະເພີ່ມໃສ່ບ່ອນນີ້."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ເຂົ້າໃຈແລ້ວ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ວິດເຈັດ"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"ເພື່ອເພີ່ມທາງລັດ \"ວິດເຈັດ\", ກະລຸນາກວດສອບວ່າໄດ້ເປີດການນຳໃຊ້ \"ສະແດງວິດເຈັດຢູ່ໜ້າຈໍລັອກ\" ໃນການຕັ້ງຄ່າແລ້ວ."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ການຕັ້ງຄ່າ"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"ປຸ່ມສະແດງພາບພັກໜ້າຈໍ"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"ສຳຫຼວດໂໝດ Hub"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"ເຂົ້າເຖິງວິດເຈັດ ແລະ ພາບພັກໜ້າຈໍທີ່ທ່ານມັກໃນລະຫວ່າງທີ່ສາກ."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"ມາເລີ່ມກັນເລີຍ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ສະຫຼັບຜູ້ໃຊ້"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ເມນູແບບດຶງລົງ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯ​ແລະ​ຂໍ້​ມູນ​ທັງ​ໝົດ​ໃນ​ເຊດ​ຊັນ​ນີ້​ຈະ​ຖືກ​ລຶບ​ອອກ."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"ກຳລັງອັບເດດ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ໂໝດຢູ່ໃນຍົນ"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"ການຄວບຄຸມຂອງພໍ່ແມ່"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ທ່ານ​ຈະ​ບໍ່​ໄດ້​ຍິນ​ສຽງ​ໂມງ​ປ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"ເວ​ລາ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"ວັນ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ສະແດງຢູ່ເທິງສຸດຂອງການແຈ້ງເຕືອນການສົນທະນາ ແລະ ເປັນຮູບໂປຣໄຟລ໌ຢູ່ໜ້າຈໍລັອກ, ປາກົດເປັນຟອງ, ສະແດງໃນໂໝດຫ້າມລົບກວນໄດ້"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ສຳຄັນ"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ຮອງຮັບຄຸນສົມບັດການສົນທະນາ"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ບໍ່ສາມາດແກ້ໄຂການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄດ້."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ບໍ່ສາມາດແກ້ໄຂການແຈ້ງເຕືອນການໂທໄດ້."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ບໍ່ສາມາດຕັ້ງຄ່າກຸ່ມການແຈ້ງເຕືອນນີ້ຢູ່ບ່ອນນີ້ໄດ້"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ປະຕິທິນ"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ຈັກຄິດໄລ່"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ແຜນທີ່"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ຫ້າມລົບກວນ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ທາງລັດປຸ່ມສຽງ"</string>
<string name="battery" msgid="769686279459897127">"ແບັດເຕີຣີ"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"ແອັບລະບົບ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ການເຮັດຫຼາຍໜ້າວຽກພ້ອມກັນ"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"ແບ່ງໜ້າຈໍ"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ການຊ່ວຍເຂົ້າເຖິງ"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ອິນພຸດ"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ທາງລັດແອັບ"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"ແອັບປັດຈຸບັນ"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ທ່ານເບິ່ງທ່າທາງຂອງແອັບຫຼ້າສຸດສຳເລັດແລ້ວ."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ເພື່ອເບິ່ງແອັບຫຼ້າສຸດ, ໃຫ້ປັດຂຶ້ນແລ້ວຄ້າງໄວ້ໂດຍໃຊ້ສາມນິ້ວເທິງແຜ່ນສຳຜັດຂອງທ່ານ"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ສະຫຼັບແອັບ"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"ໃຊ້ 4 ນິ້ວປັດຂວາເທິງແຜ່ນສຳຜັດຂອງທ່ານ"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"ດີຫຼາຍ!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"ທ່ານເຮັດທ່າທາງສະຫຼັບແອັບສຳເລັດແລ້ວ."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"ໃຊ້ 4 ນິ້ວປັດຂວາເທິງແຜ່ນສຳຜັດຂອງທ່ານເພື່ອສະຫຼັບແອັບ"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"ເບິ່ງແອັບທັງໝົດ"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ກົດປຸ່ມຄຳສັ່ງຢູ່ແປ້ນພິມຂອງທ່ານ"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ດີຫຼາຍ!"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 4292574de55e..77c92d1293c3 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Užrakinimo ekrano valdikliai"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Kad galėtumėte atidaryti programą naudodami valdiklį, turėsite patvirtinti savo tapatybę. Be to, atminkite, kad bet kas gali peržiūrėti valdiklius net tada, kai planšetinis kompiuteris užrakintas. Kai kurie valdikliai gali būti neskirti jūsų užrakinimo ekranui ir gali būti nesaugu juos čia pridėti."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Supratau"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Valdikliai"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Jei norite pridėti valdiklių šaukinį, patikrinkite, ar nustatymuose įgalinta parinktis „Rodyti valdiklius užrakinimo ekrane“."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Nustatymai"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Mygtukas „Rodyti ekrano užsklandą“"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Naršymas centro režimu"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Įkraudami pasiekite mėgstamiausius valdiklius ir ekrano užsklandas."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Pirmyn"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Perjungti naudotoją"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"išplečiamasis meniu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Atnaujinama"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Darbo profilis"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lėktuvo režimas"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Tėvų kontrolė"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Negirdėsite kito signalo <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,8 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Rodoma pokalbių pranešimų viršuje ir kaip profilio nuotrauka užrakinimo ekrane, burbule, pertraukia netrukdymo režimą"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritetiniai"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ nepalaiko pokalbių funkcijų"</string>
+ <string name="notification_inline_dismiss" msgid="88423586921134258">"Uždaryti"</string>
+ <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Neberodyti"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Šių pranešimų keisti negalima."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Skambučių pranešimų keisti negalima."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Šios grupės pranešimai čia nekonfigūruojami"</string>
@@ -912,6 +913,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendorius"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Skaičiuotuvas"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Žemėlapiai"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Netrukdymo režimas"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Garsumo mygtukų spartusis klavišas"</string>
<string name="battery" msgid="769686279459897127">"Akumuliatorius"</string>
@@ -1432,8 +1443,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Sistemos programos"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Kelių užduočių atlikimas"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Išskaidyto ekrano režimas"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Pritaikomumas"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Įvestis"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Programos spartieji klavišai"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Esama programa"</string>
@@ -1497,12 +1507,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Atlikote naujausių programų peržiūros gestą."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Peržiūrėkite naujausias programas, jutiklinėje dalyje perbraukę aukštyn trimis pirštais ir palaikę"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Perjungti programas"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Braukite dešinėn keturiais pirštais jutiklinėje dalyje"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Puiku!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Atlikote programų perjungimo gestą."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Braukite dešinėn keturiais pirštais jutiklinėje dalyje, kad perjungtumėte programas"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Žr. visas programas"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Paspauskite klaviatūros veiksmų klavišą"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Puikiai padirbėta!"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index cac42758f8bf..244376931b9e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Bloķēšanas ekrāna logrīki"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Lai atvērtu lietotni, izmantojot logrīku, jums būs jāapstiprina sava identitāte. Turklāt ņemiet vērā, ka ikviens var skatīt logrīkus, pat ja planšetdators ir bloķēts. Iespējams, daži logrīki nav paredzēti izmantošanai bloķēšanas ekrānā, un var nebūt droši tos šeit pievienot."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Labi"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Logrīki"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Lai pievienotu saīsni “Logrīki”, iestatījumos noteikti iespējojiet opciju “Rādīt logrīkus bloķēšanas ekrānā”."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Iestatījumi"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Poga “Rādīt ekrānsaudzētāju”"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mainīt lietotāju"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"novelkamā izvēlne"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tiks dzēstas visas šīs sesijas lietotnes un dati."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Notiek atjaunināšana"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Darba profils"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Lidojuma režīms"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Vecāku kontrole"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nākamais signāls (<xliff:g id="WHEN">%1$s</xliff:g>) netiks atskaņots."</string>
<string name="alarm_template" msgid="2234991538018805736">"plkst. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Parādās sarunu paziņojumu augšdaļā un kā profila attēls bloķēšanas ekrānā, arī kā burbulis, pārtrauc režīmu “Netraucēt”."</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritārs"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> netiek atbalstītas sarunu funkcijas."</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Šos paziņojumus nevar modificēt."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Paziņojumus par zvaniem nevar modificēt."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Šeit nevar konfigurēt šo paziņojumu grupu."</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendārs"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulators"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Kartes"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Režīms “Netraucēt”"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Skaļuma pogu saīsne"</string>
<string name="battery" msgid="769686279459897127">"Akumulators"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Sistēmas lietotnes"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Vairākuzdevumu režīms"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Ekrāna sadalīšana"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Pieejamība"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Ievade"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Lietotņu saīsnes"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Pašreizējā lietotne"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Jūs sekmīgi veicāt nesen izmantoto lietotņu skatīšanas žestu."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Lai skatītu nesenās lietotnes, skārienpaliktnī ar trīs pirkstiem velciet augšup un turiet"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Pārslēgšanās starp lietotnēm"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Lieliski!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Jūs sekmīgi veicāt pārslēgšanās starp lietotnēm žestu."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Skatīt visas lietotnes"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tastatūrā nospiediet darbību taustiņu."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index b53cec3636e3..a9aec1666e5a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виџети на заклучен екран"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"За да отворите апликација со помош на виџет, ќе треба да потврдите дека сте вие. Покрај тоа, имајте предвид дека секој може да ги гледа виџетите, дури и кога вашиот таблет е заклучен. Некои виџети можеби не се наменети за вашиот заклучен екран, па можеби не е безбедно да се додадат овде."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Сфатив"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виџети"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"За да ја додадете кратенката „Виџети“, погрижете се да биде овозможен „Прикажување виџети на заклучен екран“ во „Поставки“."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Поставки"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Копче за прикажување на штедачот на екран"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Промени го корисникот"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"паѓачко мени"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијава ќе се избришат."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Се ажурира"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Работен профил"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Авионски режим"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Родителски контроли"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Нема да го слушнете следниот аларм <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"во <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"во <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Се прикажува најгоре во известувањата за разговор и како профилна слика на заклучен екран, се појавува како балонче, го прекинува „Не вознемирувај“"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритетно"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддржува функции за разговор"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Овие известувања не може да се изменат"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Известувањата за повици не може да се изменат."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Оваа група известувања не може да се конфигурира тука"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калкулатор"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карти"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не вознемирувај"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Кратенка за копчињата за јачина на звук"</string>
<string name="battery" msgid="769686279459897127">"Батерија"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Системски апликации"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Мултитаскинг"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Поделен екран"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Пристапност"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Внесување"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Кратенки за апликации"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Тековна апликација"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Го завршивте движењето за прегледување на неодамнешните апликации."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Повлечете нагоре со три прста на допирната подлога и задржете за да ги видите неодамнешните апликации"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Сменете ги апликациите"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Одлично!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Го завршивте движењето за менување апликации."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Прегледајте ги сите апликации"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Притиснете го копчето за дејство на тастатурата"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 48ec2c05e95b..4c444f0d32f7 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ലോക്ക് സ്‌ക്രീൻ വിജറ്റുകൾ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"വിജറ്റ് ഉപയോഗിച്ച് ഒരു ആപ്പ് തുറക്കാൻ, ഇത് നിങ്ങൾ തന്നെയാണെന്ന് പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. നിങ്ങളുടെ ടാബ്‌ലെറ്റ് ലോക്കായിരിക്കുമ്പോഴും എല്ലാവർക്കും അത് കാണാനാകുമെന്നതും ഓർക്കുക. ചില വിജറ്റുകൾ നിങ്ങളുടെ ലോക്ക് സ്‌ക്രീനിന് ഉള്ളതായിരിക്കില്ല, അവ ഇവിടെ ചേർക്കുന്നത് സുരക്ഷിതവുമായിരിക്കില്ല."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"മനസ്സിലായി"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"വിജറ്റുകൾ"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"വിജറ്റുകൾ\" കുറുക്കുവഴി ചേർക്കാൻ, ക്രമീകരണത്തിൽ \"ലോക്ക് സ്‌ക്രീനിൽ വിജറ്റുകൾ കാണിക്കുക\" പ്രവർത്തനക്ഷമമാക്കിയെന്ന് ഉറപ്പാക്കുക."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ക്രമീകരണം"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"സ്‌ക്രീൻ സേവർ കാണിക്കുക ബട്ടൺ"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"ഹബ് മോഡ് അടുത്തറിയുക"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"ചാർജ് ചെയ്യുമ്പോൾ നിങ്ങളുടെ പ്രിയപ്പെട്ട വിജറ്റുകളും സ്‌ക്രീൻ സേവറുകളും ആക്‌സസ് ചെയ്യുക."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"തുടങ്ങാം"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ഉപയോക്താവ് മാറുക"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"പുൾഡൗൺ മെനു"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ഈ സെഷനിലെ എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"അപ്ഡേറ്റ് ചെയ്യുന്നു"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ഫ്ലൈറ്റ് മോഡ്"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"രക്ഷാകർതൃ നിയന്ത്രണങ്ങൾ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള നിങ്ങളുടെ അടുത്ത അലാറം കേൾക്കില്ല"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>-ന്"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>-ന്"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"സംഭാഷണ അറിയിപ്പുകളുടെ മുകളിലും സ്ക്രീൻ ലോക്കായിരിക്കുമ്പോൾ ഒരു പ്രൊഫൈൽ ചിത്രമായും ബബിൾ രൂപത്തിൽ ദൃശ്യമാകുന്നു, ശല്യപ്പെടുത്തരുത് മോഡ് തടസ്സപ്പെടുത്തുന്നു"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"മുൻഗണന"</string>
<string name="no_shortcut" msgid="8257177117568230126">"സംഭാഷണ ഫീച്ചറുകളെ <xliff:g id="APP_NAME">%1$s</xliff:g> പിന്തുണയ്‌ക്കുന്നില്ല"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ഈ അറിയിപ്പുകൾ പരിഷ്ക്കരിക്കാനാവില്ല."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"കോൾ അറിയിപ്പുകൾ പരിഷ്‌കരിക്കാനാകുന്നില്ല."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"അറിയിപ്പുകളുടെ ഈ ഗ്രൂപ്പ് ഇവിടെ കോണ്‍ഫിഗര്‍ ചെയ്യാൻ കഴിയില്ല"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"കാൽക്കുലേറ്റർ"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ശല്യപ്പെടുത്തരുത്"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"വോളിയം ബട്ടൺ കുറുക്കുവഴി"</string>
<string name="battery" msgid="769686279459897127">"ബാറ്ററി"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"സിസ്‌റ്റം ആപ്പുകൾ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"മൾട്ടിടാസ്‌കിംഗ്"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"സ്‌ക്രീൻ വിഭജന മോഡ്"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ഉപയോഗസഹായി"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ഇൻപുട്ട്"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ആപ്പ് കുറുക്കുവഴികൾ"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"നിലവിലെ ആപ്പ്"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"അടുത്തിടെയുള്ള ആപ്പുകൾ കാണുക എന്ന ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"സമീപകാല ആപ്പുകൾ കാണുന്നതിന്, നിങ്ങളുടെ ടച്ച്പാഡിൽ മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്‌ത് പിടിക്കുക"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ആപ്പുകൾ മാറുക"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"നിങ്ങളുടെ ടച്ച്‌പാഡിൽ നാല് വിരലുകൾ കൊണ്ട് വലത്തേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"കൊള്ളാം!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"ആപ്പുകൾ മാറൽ ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"ആപ്പുകൾ മാറാൻ നിങ്ങളുടെ ടച്ച്പാഡിൽ നാല് വിരലുകൾ കൊണ്ട് വലത്തേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"എല്ലാ ആപ്പുകളും കാണുക"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"നിങ്ങളുടെ കീബോർഡിലെ ആക്ഷൻ കീ അമർത്തുക"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"അഭിനന്ദനങ്ങൾ!"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 6effa0a5234b..3666c0d34b7a 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Түгжээтэй дэлгэцийн виджет"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Виджет ашиглан аппыг нээхийн тулд та өөрийгөө мөн болохыг баталгаажуулах шаардлагатай болно. Мөн таны таблет түгжээтэй байсан ч тэдгээрийг дурын хүн үзэж болохыг санаарай. Зарим виджет таны түгжээтэй дэлгэцэд зориулагдаагүй байж магадгүй ба энд нэмэхэд аюултай байж болзошгүй."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ойлголоо"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджет"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Виджет\"-ийн товчлол нэмэхийн тулд \"Түгжээтэй дэлгэц дээр виджет харуулах\"-ыг тохиргоонд идэвхжүүлсэн эсэхийг нягтална уу."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Тохиргоо"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Дэлгэц амраагчийг харуулах товч"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Хэрэглэгчийг сэлгэх"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"эвхмэл цэс"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ харилцан үйлдлийн бүх апп болон дата устах болно."</string>
@@ -553,7 +556,7 @@
<string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Зөвхөн нэг хэрэглэгч үүсгэх боломжтой.}other{Та # хүртэлх хэрэглэгч нэмж болно.}}"</string>
<string name="user_remove_user_title" msgid="9124124694835811874">"Хэрэглэгчийг устгах уу?"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"Энэ хэрэглэгчийн бүх апп болон мэдээлэл устах болно."</string>
- <string name="user_remove_user_remove" msgid="8387386066949061256">"Арилгах"</string>
+ <string name="user_remove_user_remove" msgid="8387386066949061256">"Хасах"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-тай бичлэг хийж эсвэл дамжуулж эхлэх үү?"</string>
<string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь бичлэг хийх эсвэл дамжуулах үед таны дэлгэцэд харуулсан эсвэл таны төхөөрөмжөөс тоглуулсан бүх мэдээлэлд хандах эрхтэй байна. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, зураг, мессеж болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string>
<string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Бичлэг хийж эсвэл дамжуулж эхлэх үү?"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Шинэчилж байна"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Ажлын профайл"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Нислэгийн горим"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Эцэг эхийн хяналт"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-т та дараагийн сэрүүлгээ сонсохгүй"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> цагт"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>-т"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Харилцан ярианы мэдэгдлийн дээд талд болон түгжигдсэн дэлгэц дээр профайл зураг байдлаар харуулах бөгөөд бөмбөлөг хэлбэрээр харагдана. Бүү саад бол горимыг тасалдуулна"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Чухал"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь харилцан ярианы онцлогуудыг дэмждэггүй"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Эдгээр мэдэгдлийг өөрчлөх боломжгүй."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Дуудлагын мэдэгдлийг өөрчлөх боломжгүй."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Энэ бүлэг мэдэгдлийг энд тохируулах боломжгүй байна"</string>
@@ -883,7 +889,7 @@
<string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Аппуудын жагсаалтыг нээх"</string>
<string name="group_system_access_system_settings" msgid="8731721963449070017">"Тохиргоог нээх"</string>
<string name="group_system_access_google_assistant" msgid="7210074957915968110">"Туслахыг нээх"</string>
- <string name="group_system_lock_screen" msgid="7391191300363416543">"Түгжээтэй дэлгэц"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Дэлгэц түгжих"</string>
<string name="group_system_quick_memo" msgid="3764560265935722903">"Тэмдэглэл хөтлөх"</string>
<string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Олон ажил зэрэг хийх"</string>
<string name="system_multitasking_rhs" msgid="8779289852395243004">"Аппыг баруун талд байгаагаар дэлгэцийг хуваахыг ашиглах"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календарь"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Тооны машин"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Газрын зураг"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Бүү саад бол"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Дууны түвшний товчлуурын товчлол"</string>
<string name="battery" msgid="769686279459897127">"Батарей"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Системийн аппууд"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Олон ажил зэрэг хийх"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Дэлгэцийг хуваах"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Хандалт"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Оролт"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Аппын товчлол"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Одоогийн апп"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Та саяхны аппуудыг харах зангааг гүйцэтгэсэн."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Саяхны аппуудыг харахын тулд мэдрэгч самбар дээрээ гурван хуруугаараа дээш шудраад, удаан дарна уу"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Апп сэлгэх"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Үнэхээр сайн ажиллалаа!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Та апп хооронд сэлгэх зангааг гүйцэтгэлээ."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Бүх аппыг харах"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Гар дээрх тусгай товчлуурыг дарна уу"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 77fd538ed398..73deadb8cae7 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"लॉक स्‍क्रीन विजेट"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"विजेट वापरून अ‍ॅप उघडण्यासाठी, तुम्हाला हे तुम्हीच असल्याची पडताळणी करावी लागेल. तसेच, लक्षात ठेवा, तुमचा टॅबलेट लॉक असतानादेखील कोणीही ती पाहू शकते. काही विजेट कदाचित तुमच्या लॉक स्‍क्रीनसाठी नाहीत आणि ती इथे जोडणे असुरक्षित असू शकते."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"समजले"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"विजेट"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"विजेट\" शॉर्टकट जोडण्यासाठी, सेटिंग्जमध्ये \"लॉक स्‍क्रीनवर विजेट दाखवा\" सुरू असल्याची खात्री करा."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"सेटिंग्ज"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"स्क्रीनसेव्हर दाखवा बटण"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"हब मोड एक्सप्लोर करा"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"चार्ज करत असताना तुमचे आवडते विजेट आणि स्क्रीन सेव्हर अ‍ॅक्सेस करा."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"चला सुरू करू या"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"वापरकर्ता स्विच करा"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनू"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अ‍ॅप्स आणि डेटा हटवला जाईल."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"अपडेट करत आहे"</string>
<string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाईल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"विमान मोड"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"पालक नियंत्रणे"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"तुम्ही तुमचा <xliff:g id="WHEN">%1$s</xliff:g> वाजता होणारा पुढील अलार्म ऐकणार नाही"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> वाजता"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> रोजी"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"संभाषण सूचनांच्या वरती आणि लॉक स्क्रीनवरील प्रोफाइल फोटो म्हणून दिसते, बबल म्हणून दिसते, व्यत्यय आणू नका यामध्ये अडथळा आणते"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राधान्य"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे संभाषण वैशिष्ट्यांना सपोर्ट करत नाही"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"या सूचनांमध्ये सुधारणा केली जाऊ शकत नाही."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कॉलशी संबंधित सूचनांमध्ये फेरबदल केला जाऊ शकत नाही."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"या सूचनांचा संच येथे कॉन्फिगर केला जाऊ शकत नाही"</string>
@@ -883,7 +886,7 @@
<string name="group_system_access_all_apps_search" msgid="1553588630154197469">"ॲप्सची सूची उघडा"</string>
<string name="group_system_access_system_settings" msgid="8731721963449070017">"सेटिंग्ज उघडा"</string>
<string name="group_system_access_google_assistant" msgid="7210074957915968110">"Assistant उघडा"</string>
- <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रीन लॉक करा"</string>
<string name="group_system_quick_memo" msgid="3764560265935722903">"नोंद घ्या"</string>
<string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"मल्टिटास्किंग"</string>
<string name="system_multitasking_rhs" msgid="8779289852395243004">"ॲप उजवीकडे ठेवून स्प्लिट स्क्रीन वापरा"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"कॅलेंडर"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"व्यत्यय आणू नका"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"आवाजाच्या बटणांचा शार्टकट"</string>
<string name="battery" msgid="769686279459897127">"बॅटरी"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"सिस्टीम अ‍ॅप्स"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"मल्टिटास्किंग"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"स्प्लिट स्क्रीन"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"अ‍ॅक्सेसिबिलिटी"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"इनपुट"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"अ‍ॅप शॉर्टकट"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"सध्याचे अ‍ॅप"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"तुम्ही अलीकडील ॲप्स पाहण्याचे जेश्चर पूर्ण केले आहे."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"अलीकडील अ‍ॅप्स पाहण्यासाठी, तुमच्या टचपॅडवर तीन बोटांनी वर स्वाइप करून धरून ठेवा"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"अ‍ॅप्स स्विच करा"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"तुमच्या टचपॅडवर चार बोटांनी उजवीकडे स्‍वाइप करा"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"उत्तम कामगिरी!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"तुम्ही अ‍ॅप्स स्विच करणे जेश्चर पूर्ण केले आहे."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"अ‍ॅप्सदरम्यान स्विच करण्यासाठी तुमच्या टचपॅडवर चार बोटांनी उजवीकडे स्‍वाइप करा"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"सर्व अ‍ॅप्स पहा"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"तुमच्या कीबोर्डवर अ‍ॅक्शन की प्रेस करा"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"खूप छान!"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 7aa95f09404d..77d2d2410878 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widget skrin kunci"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Untuk membuka apl menggunakan widget, anda perlu mengesahkan identiti anda. Selain itu, perlu diingat bahawa sesiapa sahaja boleh melihat widget tersebut, walaupun semasa tablet anda dikunci. Sesetengah widget mungkin tidak sesuai untuk skrin kunci anda dan mungkin tidak selamat untuk ditambahkan di sini."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widget"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Untuk menambahkan pintasan \"Widget\", pastikan \"Tunjukkan widget pada skrin kunci\" didayakan dalam tetapan."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Tetapan"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Tunjukkan butang penyelamat skrin"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Terokai mod hab"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Akses widget dan penyelamat skrin kegemaran anda semasa melakukan pengecasan."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Mari mulakan"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu tarik turun"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mengemaskinikan"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mod pesawat"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Kawalan ibu bapa"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar penggera yang seterusnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Ditunjukkan di bahagian atas pemberitahuan perbualan dan sebagai gambar profil pada skrin kunci, muncul sebagai gelembung, mengganggu Jangan Ganggu"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Keutamaan"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak menyokong ciri perbualan"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Pemberitahuan ini tidak boleh diubah suai."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Pemberitahuan panggilan tidak boleh diubah suai."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Kumpulan pemberitahuan ini tidak boleh dikonfigurasikan di sini"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Jangan Ganggu"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Pintasan butang kelantangan"</string>
<string name="battery" msgid="769686279459897127">"Bateri"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Apl sistem"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Berbilang tugas"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Skrin pisah"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Kebolehaksesan"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Pintasan apl"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Apl Semasa"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Anda telah melengkapkan gerak isyarat lihat apl terbaharu."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Untuk melihat apl terbaharu, leret ke atas dan tahan menggunakan tiga jari pada pad sentuh anda"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Tukar apl"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Leret ke kanan menggunakan empat jari pada pad sentuh anda"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bagus!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Anda telah melengkapkan gerak isyarat menukar apl."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Leret ke kanan menggunakan empat jari pada pad sentuh untuk beralih apl"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Lihat semua apl"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tekan kekunci tindakan pada papan kekunci anda"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Syabas!"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index d973d4066774..8f44cb0f88d3 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"လော့ခ်မျက်နှာပြင် ဝိဂျက်များ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ဝိဂျက်သုံး၍ အက်ပ်ဖွင့်ရန်အတွက် သင်ဖြစ်ကြောင်း အတည်ပြုရန်လိုသည်။ ထို့ပြင် သင့်တက်ဘလက် လော့ခ်ချထားချိန်၌ပင် မည်သူမဆို ၎င်းတို့ကို ကြည့်နိုင်ကြောင်း သတိပြုပါ။ ဝိဂျက်အချို့ကို လော့ခ်မျက်နှာပြင်အတွက် ရည်ရွယ်ထားခြင်း မရှိသဖြင့် ဤနေရာတွင် ထည့်ပါက မလုံခြုံနိုင်ပါ။"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"နားလည်ပြီ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ဝိဂျက်များ"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"“ဝိဂျက်များ” ဖြတ်လမ်းလင့်ခ်ထည့်ရန်အတွက် ဆက်တင်များတွင် “လော့ခ်မျက်နှာပြင်ပေါ်၌ ဝိဂျက်များပြရန်” ကိုဖွင့်ထားကြောင်း သေချာပါစေ။"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ဆက်တင်များ"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"စခရင်နားချိန်ပုံ ပြရန်ခလုတ်"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ဆွဲချမီနူး"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"အပ်ဒိတ်လုပ်နေသည်"</string>
<string name="status_bar_work" msgid="5238641949837091056">"အလုပ် ပရိုဖိုင်"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"လေယာဉ်ပျံမုဒ်"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"မိဘအထိန်းအချုပ်များ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> ၌သင့်နောက်ထပ် နှိုးစက်ကို ကြားမည်မဟုတ်ပါ"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ၌"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> တွင်"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"စကားဝိုင်း အကြောင်းကြားချက်များ၏ ထိပ်ပိုင်းနှင့် ပရိုဖိုင်ပုံအဖြစ် လော့ခ်မျက်နှာပြင်တွင် ပြသည်။ ပူဖောင်းကွက်အဖြစ် မြင်ရပြီး ‘မနှောင့်ယှက်ရ’ ကို ကြားဖြတ်သည်"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ဦးစားပေး"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> က စကားဝိုင်းဝန်ဆောင်မှုများကို မပံ့ပိုးပါ"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ဤအကြောင်းကြားချက်များကို ပြုပြင်၍ မရပါ။"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ခေါ်ဆိုမှုအကြောင်းကြားချက်များကို ပြင်၍မရပါ။"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ဤအကြောင်းကြားချက်အုပ်စုကို ဤနေရာတွင် စီစဉ်သတ်မှတ်၍ မရပါ"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ပြက္ခဒိန်"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ဂဏန်းတွက်စက်"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"မနှောင့်ယှက်ရ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"အသံထိန်းချုပ်သည့်ခလုတ် ဖြတ်လမ်း"</string>
<string name="battery" msgid="769686279459897127">"ဘက်ထရီ"</string>
@@ -1497,11 +1513,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"မကြာသေးမီကအက်ပ်များကို ကြည့်ခြင်းလက်ဟန် သင်ခန်းစာပြီးပါပြီ။"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"လတ်တလောအက်ပ်များကြည့်ရန် တာ့ချ်ပက်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"အက်ပ်များကူးပြောင်းခြင်း"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"တော်ပါပေသည်။"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"အက်ပ်ပြောင်းလက်ဟန် လုပ်ပြီးပါပြီ။"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"အက်ပ်အားလုံးကို ကြည့်ခြင်း"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ကီးဘုတ်တွင် လုပ်ဆောင်ချက်ကီး နှိပ်ပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0d9e2760614c..a2647728c94c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Låseskjermmoduler"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"For å åpne en app ved hjelp av en modul må du bekrefte at det er deg. Husk også at hvem som helst kan se dem, selv om nettbrettet er låst. Noen moduler er kanskje ikke laget for å være på låseskjermen og kan være utrygge å legge til der."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Greit"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Moduler"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"For å legge til «Moduler»-snarveien, sørg for at «Vis moduler på låseskjermen» er slått på i innstillingene."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Innstillinger"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Knapp for å vise skjermspareren"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Bytt bruker"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullegardinmeny"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apper og data i denne økten blir slettet."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Oppdaterer"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Work-profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flymodus"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Foreldrekontroll"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Du hører ikke neste innstilte alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Vises øverst på samtalevarsler og som et profilbilde på låseskjermen, vises som en boble, avbryter «Ikke forstyrr»"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> støtter ikke samtalefunksjoner"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Disse varslene kan ikke endres."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Anropsvarsler kan ikke endres."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Denne varselgruppen kan ikke konfigureres her"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ikke forstyrr"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Hurtigtast for volumknappene"</string>
<string name="battery" msgid="769686279459897127">"Batteri"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Systemapper"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Delt skjerm"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Tilgjengelighet"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Inndata"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"App-snarveier"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aktiv app"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du har fullført bevegelsen for å se nylige apper."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"For å se nylige apper, sveip opp og hold med tre fingre på styreflaten"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Bytt app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bra jobbet!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Du har fullført bytt-app-bevegelsen."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Se alle apper"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Trykk på handlingstasten på tastaturet"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index b1911596b2a1..ad7ffce27e26 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"लक स्क्रिन विजेटहरू"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"विजेट प्रयोग गरी एप खोल्न तपाईंले आफ्नो पहिचान पुष्टि गर्नु पर्ने हुन्छ। साथै, तपाईंको ट्याब्लेट लक भएका बेला पनि सबै जनाले तिनलाई देख्न सक्छन् भन्ने कुरा ख्याल गर्नुहोस्। केही विजेटहरू लक स्क्रिनमा प्रयोग गर्ने उद्देश्यले नबनाइएका हुन सक्छन् र तिनलाई यहाँ हाल्नु सुरक्षित नहुन सक्छ।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"बुझेँ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"विजेटहरू"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"विजेट\" सर्टकट हाल्न सेटिङमा \"लक स्क्रिनमा विजेट देखाउनुहोस्\" नामक विकल्प अन गरिएको छ भन्ने सुनिश्चित गर्नुहोस्।"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"सेटिङ"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"स्क्रिनसेभर देखाउने बटन"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"प्रयोगकर्ता फेर्नुहोस्"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनु"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"यो सत्रमा भएका सबै एपहरू र डेटा मेटाइने छ।"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"अपडेट गरिँदै छ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"अभिभावकीय नियन्त्रणहरू"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"तपाईँले आफ्नो अर्को अलार्म <xliff:g id="WHEN">%1$s</xliff:g> सुन्नुहुने छैन"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> मा"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> मा"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"यो वार्तालापका सूचनाहरूको सिरानमा, बबलका रूपमा र लक स्क्रिनमा प्रोफाइल फोटोका रूपमा देखिन्छ। साथै, यसले गर्दा \'बाधा नपुऱ्याउनुहोस्\' नामक सुविधामा अवरोध आउँछ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा वार्तालापसम्बन्धी सुविधा प्रयोग गर्न मिल्दैन"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"यी सूचनाहरू परिमार्जन गर्न मिल्दैन।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कलसम्बन्धी सूचनाहरू परिमार्जन गर्न मिल्दैन।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"यहाँबाट सूचनाहरूको यो समूह कन्फिगर गर्न सकिँदैन"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"पात्रो"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"क्याल्कुलेटर"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"नक्सा"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"बाधा नपुऱ्याउनुहोस्"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"भोल्युम बटनका सर्टकट"</string>
<string name="battery" msgid="769686279459897127">"ब्याट्री"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"सिस्टम एपहरू"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"मल्टिटास्किङ"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"स्प्लिट स्क्रिन"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"सर्वसुलभता"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"इनपुट"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"एपका सर्टकटहरू"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"हालको एप"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"तपाईंले जेस्चर प्रयोग गरी हालसालै चलाइएका एपहरू हेर्ने तरिका सिक्नुभएको छ।"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"हालसालैका एपहरू हेर्न तीन औँला प्रयोग गरी टचप्याडमा माथितिर स्वाइप गर्नुहोस् र होल्ड गर्नुहोस्"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"एपहरू बदल्नुहोस्"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"अद्भुत!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"तपाईंले एपहरू बदल्ने जेस्चर प्रयोग गर्ने तरिका सिक्नुभयो।"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"सबै एपहरू हेर्नुहोस्"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"आफ्नो किबोर्डमा भएको एक्सन की थिच्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index a3d8856625f4..b9b025ad619e 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets op het vergrendelscherm"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Als je een app wilt openen met een widget, moet je verifiëren dat jij het bent. Houd er ook rekening mee dat iedereen ze kan bekijken, ook als je tablet vergrendeld is. Bepaalde widgets zijn misschien niet bedoeld voor je vergrendelscherm en kunnen hier niet veilig worden toegevoegd."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Als je de snelkoppeling Widgets wilt toevoegen, zorg je dat Widgets tonen op het vergrendelingsscherm aanstaat in de instellingen."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Instellingen"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Knop Screensaver tonen"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Hub-modus verkennen"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Krijg toegang tot je favoriete widgets en screensavers terwijl je apparaat wordt opgeladen."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Aan de slag"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Gebruiker wijzigen"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pull-downmenu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Updaten"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuig­modus"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Ouderlijk toezicht"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"om <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"op <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wordt getoond bovenaan gespreksmeldingen en als profielfoto op het vergrendelscherm, verschijnt als bubbel, onderbreekt Niet storen"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ondersteunt geen gespreksfuncties"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Deze meldingen kunnen niet worden aangepast."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Gespreksmeldingen kunnen niet worden aangepast."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Deze groep meldingen kan hier niet worden ingesteld"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Rekenmachine"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Niet storen"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volumeknoppen als sneltoets"</string>
<string name="battery" msgid="769686279459897127">"Batterij"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Systeem-apps"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Gesplitst scherm"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Toegankelijkheid"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Invoer"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"App-sneltoetsen"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Huidige app"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Je weet nu hoe je het gebaar Recente apps bekijken maakt."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Als je recente apps wilt bekijken, swipe je met 3 vingers omhoog op de touchpad en houd je vast"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Wisselen tussen apps"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Swipe met 4 vingers naar rechts op de touchpad"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Goed werk!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Je weet nu hoe je het gebaar om van app te wisselen maakt."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Swipe met 4 vingers naar rechts op de touchpad om van app te wisselen"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Alle apps bekijken"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Druk op de actietoets op het toetsenbord"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Goed gedaan!"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index fa89a4858cdc..c0081dec369d 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ଲକ ସ୍କ୍ରିନ ୱିଜେଟ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ଏକ ୱିଜେଟ ବ୍ୟବହାର କରି ଗୋଟିଏ ଆପ ଖୋଲିବା ପାଇଁ ଏହା ଆପଣ ଅଟନ୍ତି ବୋଲି ଆପଣଙ୍କୁ ଯାଞ୍ଚ କରିବାକୁ ହେବ। ଆହୁରି ମଧ୍ୟ, ଆପଣଙ୍କ ଟାବଲେଟ ଲକ ଥିଲେ ମଧ୍ୟ ଯେ କୌଣସି ବ୍ୟକ୍ତି ଏହାକୁ ଭ୍ୟୁ କରିପାରିବେ ବୋଲି ମନେ ରଖନ୍ତୁ। କିଛି ୱିଜେଟ ଆପଣଙ୍କ ଲକ ସ୍କ୍ରିନ ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ହୋଇନଥାଇପାରେ ଏବଂ ଏଠାରେ ଯୋଗ କରିବା ଅସୁରକ୍ଷିତ ହୋଇପାରେ।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ବୁଝିଗଲି"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ୱିଜେଟ"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"ୱିଜେଟ\" ସର୍ଟକଟ ଯୋଗ କରିବାକୁ ସେଟିଂସରେ \"ଲକ ସ୍କ୍ରିନରେ ୱିଜେଟଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ\"କୁ ସକ୍ଷମ କରାଯାଇଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ସେଟିଂସ"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"ସ୍କ୍ରିନସେଭର ବଟନ ଦେଖାନ୍ତୁ"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ୟୁଜର୍‍ ବଦଳାନ୍ତୁ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ପୁଲଡାଉନ ମେନୁ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ସେସନର ସମସ୍ତ ଆପ୍‌ ଓ ଡାଟା ଡିଲିଟ୍‌ ହୋଇଯିବ।"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"ଅପଡେଟ ହେଉଛି"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ଏୟାରପ୍ଲେନ ମୋଡ"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"ବାପାମାଙ୍କ ନିୟନ୍ତ୍ରଣ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ହେଲେ"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> ବେଳେ"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ବାର୍ତ୍ତାଳାପ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଶୀର୍ଷରେ ଏବଂ ଲକ୍ ସ୍କ୍ରିନରେ ଏକ ପ୍ରୋଫାଇଲ୍ ଛବି ଭାବେ ଦେଖାଏ, ଏକ ବବଲ୍ ଭାବେ ଦେଖାଯାଏ, \'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\'କୁ ବାଧା ଦିଏ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ପ୍ରାଥମିକତା"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବାର୍ତ୍ତାଳାପ ଫିଚରଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ ନାହିଁ"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିବର୍ତ୍ତନ କରିହେବ ନାହିଁ।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"କଲ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରାଯାଇପାରିବ ନାହିଁ।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ଏଠାରେ ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଗ୍ରୁପ୍ କନଫ୍ୟୁଗର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"କାଲକୁଲେଟର"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ଭଲ୍ୟୁମ ବଟନ୍‍ ଶର୍ଟକଟ୍‍"</string>
<string name="battery" msgid="769686279459897127">"ବେଟେରୀ"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"ସିଷ୍ଟମ ଆପ୍ସ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ମଲ୍ଟିଟାସ୍କିଂ"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ଆକ୍ସେସିବିଲିଟୀ"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ଇନପୁଟ"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ଆପ ସର୍ଟକଟ"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"ବର୍ତ୍ତମାନର ଆପ"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ଆପଣ ବର୍ତ୍ତମାନର ଆପ୍ସ ଜେଶ୍ଚରକୁ ଭ୍ୟୁ କରିବା ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରିବାକୁ, ଆପଣଙ୍କ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ଆପ୍ସକୁ ସୁଇଚ କରନ୍ତୁ"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"ବଢ଼ିଆ କାମ!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"ଆପଣ ସୁଇଚ ଆପ୍ସ ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"ସବୁ ଆପ ଭ୍ୟୁ କରନ୍ତୁ"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ଆପଣଙ୍କର କୀବୋର୍ଡରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index a0c06122b7a4..23a94b00aece 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"ਲਾਕ ਸਕ੍ਰੀਨ ਵਿਜੇਟ"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ਵਿਜੇਟ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਐਪ ਖੋਲ੍ਹਣ ਲਈ, ਤੁਹਾਨੂੰ ਇਹ ਪੁਸ਼ਟੀ ਕਰਨ ਦੀ ਲੋੜ ਪਵੇਗੀ ਕਿ ਇਹ ਤੁਸੀਂ ਹੀ ਹੋ। ਨਾਲ ਹੀ, ਇਹ ਵੀ ਧਿਆਨ ਵਿੱਚ ਰੱਖੋ ਕਿ ਕੋਈ ਵੀ ਉਨ੍ਹਾਂ ਨੂੰ ਦੇਖ ਸਕਦਾ ਹੈ, ਭਾਵੇਂ ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਲਾਕ ਹੋਵੇ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕੁਝ ਵਿਜੇਟ ਤੁਹਾਡੀ ਲਾਕ ਸਕ੍ਰੀਨ ਲਈ ਨਾ ਬਣੇ ਹੋਣ ਅਤੇ ਉਨ੍ਹਾਂ ਨੂੰ ਇੱਥੇ ਸ਼ਾਮਲ ਕਰਨਾ ਅਸੁਰੱਖਿਅਤ ਹੋਵੇ।"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ਸਮਝ ਲਿਆ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ਵਿਜੇਟ"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"ਵਿਜੇਟ\" ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਲਈ, ਪੱਕਾ ਕਰੋ ਕਿ ਸੈਟਿੰਗਾਂ ਵਿੱਚ \"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਦਿਖਾਓ\" ਚਾਲੂ ਹੈ।"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ਸੈਟਿੰਗਾਂ"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"\'ਸਕ੍ਰੀਨ-ਸੇਵਰ ਦਿਖਾਓ\' ਬਟਨ"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"ਹੱਬ ਮੋਡ ਦੀ ਪੜਚੋਲ ਕਰੋ"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"ਚਾਰਜ ਕਰਨ ਵੇਲੇ ਆਪਣੇ ਮਨਪਸੰਦ ਵਿਜੇਟਾਂ ਅਤੇ ਸਕ੍ਰੀਨ ਸੇਵਰਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰੋ।"</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"ਚਲੋ ਸ਼ੁਰੂ ਕਰੀਏ"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ਪੁੱਲਡਾਊਨ ਮੀਨੂ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿਚਲੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟੇ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"ਮਾਪਿਆਂ ਦੇ ਕੰਟਰੋਲ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ਗੱਲਬਾਤ ਸੂਚਨਾਵਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਵਜੋਂ ਦਿਖਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ, ਜੋ ਕਿ ਬਬਲ ਵਜੋਂ ਦਿਸਦੀਆਂ ਹਨ ਅਤੇ \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਸੁਵਿਧਾ ਵਿੱਚ ਵਿਘਨ ਵੀ ਪਾ ਸਕਦੀਆਂ ਹਨ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ਤਰਜੀਹ"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਗੱਲਬਾਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ਕਾਲ ਸੰਬੰਧੀ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ਇਹ ਸੂਚਨਾਵਾਂ ਦਾ ਗਰੁੱਪ ਇੱਥੇ ਸੰਰੂਪਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ਨਕਸ਼ੇ"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ਵੌਲਿਊਮ ਬਟਨ ਸ਼ਾਰਟਕੱਟ"</string>
<string name="battery" msgid="769686279459897127">"ਬੈਟਰੀ"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"ਸਿਸਟਮ ਐਪਾਂ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ਮਲਟੀਟਾਸਕਿੰਗ"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ਪਹੁੰਚਯੋਗਤਾ"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ਇਨਪੁੱਟ"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ਐਪ ਸ਼ਾਰਟਕੱਟ"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"ਮੌਜੂਦਾ ਐਪ"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ਤੁਸੀਂ \'ਹਾਲੀਆ ਐਪਾਂ ਦੇਖੋ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ ਹੈ।"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ਹਾਲੀਆ ਐਪਾਂ ਦੇਖਣ ਲਈ, ਆਪਣੇ ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਵਰਤ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਕੇ ਰੋਕ ਕੇ ਰੱਖੋ"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ਐਪਾਂ ਵਿਚਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"ਆਪਣੇ ਟੱਚਪੈਡ \'ਤੇ ਚਾਰ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"ਬਹੁਤ ਵਧੀਆ!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"ਤੁਸੀਂ ਐਪ ਸਵਿੱਚ ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"ਐਪਾਂ ਬਦਲਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ \'ਤੇ ਚਾਰ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"ਸਾਰੀਆਂ ਐਪਾਂ ਦੇਖੋ"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ਆਪਣੇ ਕੀ-ਬੋਰਡ \'ਤੇ ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਦਬਾਓ"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ਬਹੁਤ ਵਧੀਆ!"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 031311741a55..fd41419a5fea 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widżety na ekranie blokady"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Aby otworzyć aplikację za pomocą widżetu, musisz potwierdzić swoją tożsamość. Pamiętaj też, że każdy będzie mógł wyświetlić widżety nawet wtedy, gdy tablet będzie zablokowany. Niektóre widżety mogą nie być przeznaczone do umieszczenia na ekranie blokady i ich dodanie w tym miejscu może być niebezpieczne."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widżety"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Aby dodać skrót „Widżety”, upewnij się, że opcja „Pokaż widżety na ekranie blokady” jest włączona w ustawieniach."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ustawienia"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Przycisk Pokaż wygaszacz ekranu"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Aktualizuję"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Kontrola rodzicielska"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nie usłyszysz swojego następnego alarmu <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"w: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek, przerywa działanie trybu Nie przeszkadzać"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorytetowe"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje funkcji rozmów"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Tych powiadomień nie można zmodyfikować."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Powiadomień o połączeniach nie można modyfikować."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Tej grupy powiadomień nie można tu skonfigurować"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendarz"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapy"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Nie przeszkadzać"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Wł./wył. przyciskami głośności"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplikacje systemowe"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Wielozadaniowość"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Podzielony ekran"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Ułatwienia dostępu"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Wprowadzanie"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Skróty do aplikacji"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Bieżąca aplikacja"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Znasz już gest wyświetlania ostatnio używanych aplikacji."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Aby wyświetlić ostatnie aplikacje, przesuń 3 palcami w górę na touchpadzie i przytrzymaj"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Przełączanie aplikacji"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Brawo!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Gest do przełączania aplikacji został opanowany."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Wyświetl wszystkie aplikacje"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Naciśnij klawisz działania na klawiaturze"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index e21554cb9e6f..b31296d14ec1 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da tela de bloqueio"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir um app usando um widget, você precisa confirmar sua identidade. E não se esqueça que qualquer pessoa pode ver os widgets, mesmo com o tablet bloqueado. Além disso, alguns apps não foram criados para a tela de bloqueio, é melhor manter a segurança."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para adicionar o atalho Widgets, verifique se a opção \"Mostrar widgets na tela de bloqueio\" está ativada nas configurações."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configurações"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botão \"Mostrar protetor de tela\""</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Atualizando"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controles da família"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparecem na parte superior das notificações de conversa, como uma foto do perfil na tela de bloqueio e como um balão. Interrompem o Não perturbe."</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
<string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar essas notificações."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamada."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar esse grupo de notificações aqui"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapas"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Não perturbe"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atalho de botões de volume"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Apps do sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitarefas"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Tela dividida"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Acessibilidade"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrada"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Atalhos de apps"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"App atual"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Você concluiu o gesto para ver os apps recentes."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Se quiser ver os apps recentes, deslize para cima e pressione o touchpad com três dedos"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Mudar de app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Muito bem!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Você concluiu o gesto para mudar de app."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todos os apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pressione a tecla de ação no teclado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f5c29d485130..9187391a15d6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets do ecrã de bloqueio"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir uma app através de um widget, vai ter de validar a sua identidade. Além disso, tenha em atenção que qualquer pessoa pode ver os widgets, mesmo quando o tablet estiver bloqueado. Alguns widgets podem não se destinar ao ecrã de bloqueio e pode ser inseguro adicioná-los aqui."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para adicionar o atalho \"Widgets\", certifique-se de que a opção \"Mostrar widgets no ecrã de bloqueio\" está ativada nas definições."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Definições"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botão Mostrar proteção de ecrã"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Explore o modo Hub"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Aceda aos seus widgets e proteções de ecrã favoritos durante o carregamento."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Começar"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mudar utilizador"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pendente"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"A atualizar"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avião"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controlos parentais"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Não vai ouvir o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"em <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparece na parte superior das notificações de conversas e como uma imagem do perfil no ecrã de bloqueio, surge como um balão, interrompe o modo Não incomodar"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
<string name="no_shortcut" msgid="8257177117568230126">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> não suporta funcionalidades de conversa."</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar estas notificações."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamadas."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar este grupo de notificações aqui."</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendário"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Não incomodar"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atalho dos botões de volume"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Apps do sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Ecrã dividido"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Acessibilidade"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrada"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Atalhos de apps"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"App atual"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Concluiu o gesto para ver as apps recentes."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Para ver as apps recentes, deslize rapidamente para cima sem soltar com 3 dedos no touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Mudar de app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Deslize rapidamente para a direita com 4 dedos no touchpad"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Muito bem!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Concluiu o gesto para alternar entre apps."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Deslize rapidamente para a direita com 4 dedos no touchpad para mudar de app"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas as apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Prima a tecla de ação no teclado"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Muito bem!"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index e21554cb9e6f..b31296d14ec1 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgets da tela de bloqueio"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para abrir um app usando um widget, você precisa confirmar sua identidade. E não se esqueça que qualquer pessoa pode ver os widgets, mesmo com o tablet bloqueado. Além disso, alguns apps não foram criados para a tela de bloqueio, é melhor manter a segurança."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Entendi"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para adicionar o atalho Widgets, verifique se a opção \"Mostrar widgets na tela de bloqueio\" está ativada nas configurações."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configurações"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botão \"Mostrar protetor de tela\""</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Atualizando"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Controles da família"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparecem na parte superior das notificações de conversa, como uma foto do perfil na tela de bloqueio e como um balão. Interrompem o Não perturbe."</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
<string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar essas notificações."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamada."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar esse grupo de notificações aqui"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapas"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Não perturbe"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atalho de botões de volume"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Apps do sistema"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitarefas"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Tela dividida"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Acessibilidade"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrada"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Atalhos de apps"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"App atual"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Você concluiu o gesto para ver os apps recentes."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Se quiser ver os apps recentes, deslize para cima e pressione o touchpad com três dedos"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Mudar de app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Muito bem!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Você concluiu o gesto para mudar de app."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todos os apps"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pressione a tecla de ação no teclado"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7a9ea1fa10fd..fc23118a8c8c 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgeturi pe ecranul de blocare"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Pentru a deschide o aplicație folosind un widget, va trebui să-ți confirmi identitatea. În plus, reține că oricine poate să vadă widgeturile, chiar dacă tableta este blocată. Este posibil ca unele widgeturi să nu fi fost create pentru ecranul de blocare și poate fi nesigur să le adaugi aici."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgeturi"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Pentru a adăuga comanda rapidă Widgeturi, verifică dacă opțiunea Afișează widgeturi pe ecranul de blocare este activată în setări."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Setări"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Butonul Afișează screensaverul"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Schimbă utilizatorul"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"meniu vertical"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toate aplicațiile și datele din această sesiune vor fi șterse."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Se actualizează"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil de serviciu"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Mod Avion"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Control parental"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nu vei auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"la <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Se afișează în partea de sus a notificărilor pentru conversații și ca fotografie de profil pe ecranul de blocare, apare ca un balon, întrerupe funcția Nu deranja"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritate"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu acceptă funcții pentru conversații"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Aceste notificări nu pot fi modificate."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Notificările pentru apeluri nu pot fi modificate."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Acest grup de notificări nu poate fi configurat aici"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Nu deranja"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Comandă rapidă din butoanele de volum"</string>
<string name="battery" msgid="769686279459897127">"Baterie"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplicații de sistem"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Ecran împărțit"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accesibilitate"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Intrare"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Comenzi rapide pentru aplicații"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aplicația actuală"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ai finalizat gestul pentru afișarea aplicațiilor recente."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Ca să vezi aplicațiile recente, glisează în sus și ține apăsat cu trei degete pe touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Comută între aplicații"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Excelent!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Ai finalizat gestul de trecere la altă aplicație."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Vezi toate aplicațiile"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Apasă tasta de acțiuni de pe tastatură"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index f5b33742c8cb..5b0ce2e7da0e 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виджеты на заблокированном экране"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Чтобы открыть приложение, используя виджет, вам нужно будет подтвердить свою личность. Обратите внимание, что виджеты видны всем, даже если планшет заблокирован. Некоторые виджеты не предназначены для использования на заблокированном экране. Добавлять их туда может быть небезопасно."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"ОК"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджеты"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Чтобы создать ярлык \"Виджеты\", убедитесь, что в настройках включена функция \"Показывать виджеты на заблокированном экране\"."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Настройки"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Кнопка \"Показать заставку\""</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Сменить пользователя."</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"раскрывающееся меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Все приложения и данные этого профиля будут удалены."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Обновление"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Рабочий профиль"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим полета"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Родительский контроль"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Следующий будильник: <xliff:g id="WHEN">%1$s</xliff:g>. Звук отключен."</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает функции разговоров."</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Эти уведомления нельзя изменить."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Уведомления о звонках нельзя изменить."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Эту группу уведомлений нельзя настроить здесь."</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календарь"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калькулятор"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карты"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не беспокоить"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Кнопки регулировки громкости"</string>
<string name="battery" msgid="769686279459897127">"Батарея"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Системные приложения"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Многозадачность"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Разделение экрана"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Специальные возможности"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Ввод"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Приложения"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Это приложение"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Вы выполнили жест для просмотра недавних приложений."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Чтобы увидеть недавние приложения, проведите по сенсорной панели тремя пальцами вверх и удерживайте."</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Переход в другое приложение"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Отлично!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Вы выполнили жест перехода в другое приложение."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Все приложения"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Нажмите клавишу действия на клавиатуре."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index a9ea2ae68a89..1c250118299e 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"අගුළු තිර විජට්"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"විජට් එකක් භාවිතයෙන් යෙදුමක් විවෘත කිරීමට, ඔබට ඒ ඔබ බව සත්‍යාපනය කිරීමට අවශ්‍ය වනු ඇත. එසේම, ඔබේ ටැබ්ලටය අගුළු දමා ඇති විට පවා ඕනෑම කෙනෙකුට ඒවා බැලිය හැකි බව මතක තබා ගන්න. සමහර විජට් ඔබේ අගුළු තිරය සඳහා අදහස් කර නොතිබිය හැකි අතර මෙහි එක් කිරීමට අනාරක්ෂිත විය හැක."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"තේරුණා"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"විජට්"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"විජට්\" කෙටිමඟ එක් කිරීමට, සැකසීම් තුළ \"අගුළු තිරයෙහි විජට් පෙන්වන්න\" සබල කර ඇති බවට වග බලා ගන්න."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"සැකසීම්"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"තිර සුරැකුම් බොත්තම පෙන්වන්න"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"පරිශීලක මාරුව"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"නිපතන මෙනුව"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"යාවත්කාලීන කිරීම"</string>
<string name="status_bar_work" msgid="5238641949837091056">"කාර්යාල පැතිකඩ"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ගුවන්යානා ප්‍රකාරය"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"මාපිය පාලන"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"ඔබට ඔබේ ඊළඟ එලාමය <xliff:g id="WHEN">%1$s</xliff:g> නොඇසෙනු ඇත"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ට"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> දී"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"සංවාද දැනුම්දීම්වල ඉහළින්ම සහ අගුලු තිරයේ ඇති පැතිකඩ පින්තූරයක් ලෙස පෙන්වයි, බුබුළක් ලෙස දිස් වේ, බාධා නොකරන්න සඳහා බාධා කරයි"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ප්‍රමුඛතාව"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> සංවාද විශේෂාංගවලට සහාය නොදක්වයි"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"මෙම දැනුම්දීම් වෙනස් කළ නොහැක."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ඇමතුම් දැනුම්දීම් වෙනස් කළ නොහැකිය."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"මෙම දැනුම්දීම් සමූහය මෙහි වින්‍යාස කළ නොහැක"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"දින දර්ශනය"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ගණකය"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"සිතියම්"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"බාධා නොකරන්න"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"හඩ පරිමා බොත්තම් කෙටිමග"</string>
<string name="battery" msgid="769686279459897127">"බැටරිය"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"පද්ධති යෙදුම්"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"බහුකාර්ය"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"බෙදුම් තිරය"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ප්‍රවේශ්‍යතාව"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ආදානය"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"යෙදුම් කෙටිමං"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"වත්මන් යෙදුම"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ඔබ මෑත යෙදුම් ඉංගිත බැලීම සම්පූර්ණ කර ඇත."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"මෑත කාලීන යෙදුම් බැලීමට, ඔබේ ස්පර්ශක පෑඩයේ ඇඟිලි තුනක් භාවිතයෙන් ඉහළට ස්වයිප් කරගෙන සිටින්න"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"යෙදුම් මාරු කරන්න"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"අනර්ඝ වැඩක්!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"ඔබ යෙදුම් මාරු කිරීමේ ඉංගිතය සම්පූර්ණ කර ඇත."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"සියලු යෙදුම් බලන්න"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ඔබේ යතුරු පුවරුවේ ක්‍රියාකාරී යතුර ඔබන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 406f423a18d0..07eb200d5bda 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Miniaplikácie na uzamknutej obrazovke"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ak chcete otvoriť aplikáciu pomocou miniaplikácie, budete musieť overiť svoju totožnosť. Pamätajte, že si miniaplikáciu môže pozrieť ktokoľvek, aj keď máte tablet uzamknutý. Niektoré miniaplikácie možno nie sú určené pre uzamknutú obrazovku a ich pridanie tu môže byť nebezpečné."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Dobre"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Miniaplikácie"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Ak chcete pridať odkaz Miniaplikácie, uistite sa, že v nastaveniach je zapnutá možnosť Zobrazovať miniaplikácie na uzamknutej obrazovke."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Nastavenia"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Zobraziť tlačidlo šetriča obrazovky"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Prepnutie používateľa"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbaľovacia ponuka"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Všetky aplikácie a údaje v tejto relácii budú odstránené."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Aktualizuje sa"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Pracovný profil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Režim v lietadle"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Rodičovská kontrola"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Váš budík o <xliff:g id="WHEN">%1$s</xliff:g> sa nespustí"</string>
<string name="alarm_template" msgid="2234991538018805736">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje sa ako bublina v hornej časti upozornení konverzácie a profilová fotka na uzamknutej obrazovke, preruší režim bez vyrušení"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritné"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nepodporuje funkcie konverzácie"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Tieto upozornenia sa nedajú upraviť."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornenia na hovory sa nedajú upraviť."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Túto skupinu upozornení nejde na tomto mieste konfigurovať"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendár"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulačka"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapy"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Režim bez vyrušení"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Skratka tlačidiel hlasitosti"</string>
<string name="battery" msgid="769686279459897127">"Batéria"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Systémové aplikácie"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Rozdelená obrazovka"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Dostupnosť"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Vstup"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Skratky aplikácií"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aktuálna aplikácia"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Použili ste gesto na zobrazenie nedávnych aplikácií."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Ak si chcete zobraziť nedávne aplikácie, potiahnite troma prstami na touchpade nahor a pridržte ich"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Prepínanie aplikácií"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Skvelé!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Dokončili ste gesto na prepnutie aplikácií."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Zobrazenie všetkých aplikácií"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Stlačte na klávesnici akčný kláves"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 7127bed39f6b..e0c65e34e038 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Pripomočki na zaklenjenem zaslonu"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Če želite aplikacijo odpreti s pripomočkom, morate potrditi, da ste to vi. Upoštevajte tudi, da si jih lahko ogledajo vsi, tudi ko je tablični računalnik zaklenjen. Nekateri pripomočki morda niso predvideni za uporabo na zaklenjenem zaslonu, zato jih tukaj morda ni varno dodati."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Razumem"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Pripomočki"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Če želite dodati bližnjico »Pripomočki«, v nastavitvah omogočite možnost »Prikaz pripomočkov na zaklenjenem zaslonu«."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Nastavitve"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Pokaži gumb za ohranjevalnik zaslona"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Raziščite način središča"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Med polnjenjem dostopajte do priljubljenih pripomočkov in ohranjevalnikov zaslona."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Pa začnimo"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"spustni meni"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Posodabljanje"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profil za Android Work"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Način za letalo"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Starševski nadzor"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Naslednjega alarma ob <xliff:g id="WHEN">%1$s</xliff:g> ne boste slišali"</string>
<string name="alarm_template" msgid="2234991538018805736">"ob <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"ob tem času: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,8 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikaz v obliki oblačka na vrhu razdelka z obvestili za pogovor in kot profilna slika na zaklenjenem zaslonu, preglasitev načina Ne moti."</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prednostno"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podpira pogovornih funkcij."</string>
+ <string name="notification_inline_dismiss" msgid="88423586921134258">"Opusti"</string>
+ <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Tega ne prikaži več"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Za ta obvestila ni mogoče spremeniti nastavitev."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obvestil o klicih ni mogoče spreminjati."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Te skupine obvestil ni mogoče konfigurirati tukaj"</string>
@@ -912,6 +913,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Koledar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Računalo"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Zemljevidi"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne moti"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Bližnjica z gumboma za glasnost"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -1432,8 +1443,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Sistemske aplikacije"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Večopravilnost"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Razdeljen zaslon"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Dostopnost"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Vnos"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Bližnjice do aplikacij"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Trenutna aplikacija"</string>
@@ -1497,12 +1507,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Izvedli ste potezo za ogled nedavnih aplikacij."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Za ogled nedavnih aplikacij povlecite s tremi prsti navzgor po sledilni ploščici in pridržite"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Preklop aplikacij"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Na sledilni ploščici s štirimi prsti povlecite desno"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Odlično!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Izvedli ste potezo za preklop med aplikacijami."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Na sledilni ploščici s štirimi prsti povlecite desno, da preklopite med aplikacijami"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Ogled vseh aplikacij"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite tipko za dejanja na tipkovnici"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Odlično!"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index b02434a810a9..f6bd8b5645c7 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Miniaplikacionet në ekranin e kyçjes"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Për të hapur një aplikacion duke përdorur një miniaplikacion, do të duhet të verifikosh që je ti. Ki parasysh gjithashtu që çdo person mund t\'i shikojë, edhe kur tableti yt është i kyçur. Disa miniaplikacione mund të mos jenë planifikuar për ekranin tënd të kyçjes dhe mund të mos jetë e sigurt t\'i shtosh këtu."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"E kuptova"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Miniaplikacionet"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Për të shtuar shkurtoren e \"Miniaplikacioneve\", sigurohu që \"Shfaq miniaplikacionet në ekranin e kyçjes\" të jetë aktivizuar te cilësimet."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Cilësimet"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Shfaq butonin e mbrojtësit të ekranit"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Ndërro përdorues"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyja me tërheqje poshtë"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Të gjitha aplikacionet dhe të dhënat në këtë sesion do të fshihen."</string>
@@ -802,6 +805,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shfaqet në krye të njoftimeve të bisedës dhe si fotografia e profilit në ekranin e kyçjes, shfaqet si flluskë dhe ndërpret modalitetin \"Mos shqetëso\""</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Me përparësi"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mbështet veçoritë e bisedës"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Këto njoftime nuk mund të modifikohen."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Njoftimet e telefonatave nuk mund të modifikohen."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ky grup njoftimesh nuk mund të konfigurohet këtu"</string>
@@ -912,6 +919,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendari"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Makina llogaritëse"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Mos shqetëso"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Shkurtorja e butonave të volumit"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -1432,8 +1449,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Aplikacionet e sistemit"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Kryerja e shumë detyrave"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Ekrani i ndarë"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Qasshmëria"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Hyrja"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Shkurtoret e aplikacionit"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aplikacioni aktual"</string>
@@ -1497,11 +1513,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Përfundove gjestin për shikimin e aplikacioneve të fundit."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Për të shikuar aplikacionet e fundit, rrëshqit shpejt lart dhe mbaj shtypur me tre gishta në bllokun me prekje"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Ndërro aplikacionet"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Punë e shkëlqyer!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"E ke përfunduar gjestin e ndërrimit të aplikacioneve."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Shiko të gjitha aplikacionet"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Shtyp tastin e veprimit në tastierë"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 70967419276b..9232888a5d94 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Виџети за закључани екран"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Да бисте отворили апликацију која користи виџет, треба да потврдите да сте то ви. Имајте у виду да свако може да га види, чак и када је таблет закључан. Неки виџети можда нису намењени за закључани екран и можда није безбедно да их тамо додате."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Важи"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виџети"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Да бисте додали пречицу Виџети, уверите се да је у подешавањима омогућено Приказуј виџете на закључаном екрану."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Подешавања"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Дугме Прикажи чувар екрана"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Истражите режим центра"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Приступајте омиљеним виџетима и чуварима екрана током пуњења."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Идемо"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Замени корисника"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падајући мени"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Све апликације и подаци у овој сесији ће бити избрисани."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ажурира се"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Пословни профил"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Режим рада у авиону"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Родитељски надзор"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Нећете чути следећи аларм у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Приказује се у врху обавештења о конверзацијама и као слика профила на закључаном екрану, појављује се као облачић, прекида режим Не узнемиравај"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритетно"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не подржава функције конверзације"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ова обавештења не могу да се мењају."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Обавештења о позивима не могу да се мењају."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ова група обавештења не може да се конфигурише овде"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калкулатор"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Мапе"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не узнемиравај"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Пречица за дугмад за јачину звука"</string>
<string name="battery" msgid="769686279459897127">"Батерија"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Системске апликације"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Обављање више задатака истовремено"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Подељени екран"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Приступачност"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Унос"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Пречице за апликације"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Актуелна апликација"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Довршили сте покрет за приказивање недавно коришћених апликација."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Да бисте прегледали недавне апликације, превуците нагоре и задржите са три прста на тачпеду"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Пређи на другу апликацију"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Превуците удесно са четири прста на тачпеду"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Одлично!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Довршили сте покрет за промену апликација."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Превуците улево са четири прста на тачпеду да бисте прешли на другу апликацију"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Прикажи све апликације"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Притисните тастер радњи на тастатури"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Одлично!"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 4e64e5a80d31..cfa9c0a4709c 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Widgetar för låsskärm"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Du måste verifiera din identitet innan du öppnar en app med en widget. Tänk också på att alla kan se dem, även när surfplattan är låst. Vissa widgetar kanske inte är avsedda för låsskärmen och det kan vara osäkert att lägga till dem här."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgetar"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Om du vill lägga till genvägen Widgetar måste du se till att Visa widgetar på låsskärmen är aktiverat i inställningarna."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Inställningar"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Visa skärmsläckarknappen"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Byt användare"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullgardinsmeny"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Uppdaterar"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Jobbprofil"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Flygplansläge"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Föräldrakontroller"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Nästa alarm, kl. <xliff:g id="WHEN">%1$s</xliff:g>, kommer inte att höras"</string>
<string name="alarm_template" msgid="2234991538018805736">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Visas högst upp i konversationsaviseringarna och som profilbild på låsskärmen, visas som bubbla, åsidosätter Stör ej"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inte stöd för konversationsfunktioner"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Det går inte att ändra de här aviseringarna."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Det går inte att ändra samtalsaviseringarna."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Den här aviseringsgruppen kan inte konfigureras här"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkylator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Kartor"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Stör ej"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Genväg till volymknappar"</string>
<string name="battery" msgid="769686279459897127">"Batteri"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Systemappar"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multikörning"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Delad skärm"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Tillgänglighet"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Inmatning"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Genvägar till appar"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aktuell app"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du är klar med rörelsen för att se de senaste apparna."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Svep uppåt på styrplattan med tre fingrar och håll kvar för att se nyligen använda appar"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Byta app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Bra jobbat!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Du har slutfört rörelsen för att byta app"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Visa alla appar"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tryck på åtgärdstangenten på tangentbordet"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index ecba5597e588..9ec763b3d9bd 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Wijeti zinazoonekana kwenye skrini iliyofungwa"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Utahitaji kuthibitisha kuwa ni wewe ili ufungue programu ukitumia wijeti. Pia, kumbuka kuwa mtu yeyote anaweza kuziona, hata kishikwambi chako kikiwa kimefungwa. Huenda baadhi ya wijeti hazikukusudiwa kutumika kwenye skrini yako iliyofungwa na huenda si salama kuziweka hapa."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Nimeelewa"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Wijeti"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Ili uweke njia ya mkato ya \"Wijeti\", hakikisha kuwa kitufe cha \"Onyesha wijeti kwenye skrini iliyofungwa\" kimewashwa katika mipangilio."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Mipangilio"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Kitufe cha “Onyesha taswira ya skrini”"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Badili mtumiaji"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyu ya kuvuta chini"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Inasasisha"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Vidhibiti vya wazazi"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Hutasikia kengele yako inayofuata ya saa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"saa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"siku ya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Huonyeshwa kwenye sehemu ya juu ya arifa za mazungumzo na kama picha ya wasifu kwenye skrini iliyofungwa. Huonekana kama kiputo na hukatiza kipengele cha Usinisumbue"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Kipaumbele"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> haitumii vipengele vya mazungumzo"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Arifa hizi haziwezi kubadilishwa."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Arifa za simu haziwezi kubadilishwa."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Kikundi hiki cha arifa hakiwezi kuwekewa mipangilio hapa"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalenda"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kikokotoo"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Ramani"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Usinisumbue"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Njia ya mkato ya vitufe vya sauti"</string>
<string name="battery" msgid="769686279459897127">"Betri"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Programu za mfumo"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Majukumu mengi"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Gawa skrini"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Ufikivu"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Kifaa cha kuingiza data"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Njia za mikato za programu"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Programu Inayotumika Sasa"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Umekamilisha mafunzo ya mguso wa kuangalia programu za hivi majuzi."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Telezesha vidole vitatu juu na ushikilie kwenye padi yako ya kugusa ili uangalie programu za hivi majuzi"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Badilisha programu"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Kazi nzuri!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Umekamilisha mafunzo kuhusu mguso wa kubadili programu."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Angalia programu zote"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Bonyeza kitufe cha vitendo kwenye kibodi yako"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index d6e5be4c1bd5..bca92d3834d1 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"பூட்டுத் திரை விட்ஜெட்கள்"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"விட்ஜெட்டைப் பயன்படுத்தி ஆப்ஸைத் திறக்க, அது நீங்கள்தான் என்பதை உறுதிசெய்ய வேண்டும். அத்துடன், உங்கள் டேப்லெட் பூட்டப்பட்டிருந்தாலும்கூட அவற்றை யார் வேண்டுமானாலும் பார்க்கலாம் என்பதை நினைவில்கொள்ளுங்கள். சில விட்ஜெட்கள் உங்கள் பூட்டுத் திரைக்காக உருவாக்கப்பட்டவை அல்ல என்பதையும் அவற்றை இங்கே சேர்ப்பது பாதுகாப்பற்றதாக இருக்கக்கூடும் என்பதையும் நினைவில்கொள்ளுங்கள்."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"சரி"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"விட்ஜெட்கள்"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"“விட்ஜெட்கள்” ஷார்ட்கட்டைச் சேர்க்க, அமைப்புகளில் “பூட்டுத் திரையில் விட்ஜெட்களைக் காட்டுதல்” அமைப்பு இயக்கப்பட்டிருப்பதை உறுதிசெய்துகொள்ளுங்கள்."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"அமைப்புகள்"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"ஸ்கிரீன் சேவரைக் காட்டும் பட்டன்"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"பயனரை மாற்று"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"கீழ் இழுக்கும் மெனு"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"இந்த அமர்வின் எல்லா ஆப்ஸும் தரவும் நீக்கப்படும்."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"புதுப்பிக்கிறது"</string>
<string name="status_bar_work" msgid="5238641949837091056">"பணிக் கணக்கு"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"விமானப் பயன்முறை"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"பெற்றோர் கட்டுப்பாடுகள்"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"அடுத்த அலாரத்தை <xliff:g id="WHEN">%1$s</xliff:g> மணிக்கு கேட்க மாட்டீர்கள்"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> மணிக்கு"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> மணிக்கு"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"உரையாடல் அறிவிப்புகளின் மேற்பகுதியில் காட்டப்படும், திரை பூட்டப்பட்டிருக்கும்போது சுயவிவரப் படமாகக் காட்டப்படும், குமிழாகத் தோன்றும், தொந்தரவு செய்ய வேண்டாம் அம்சம் இயக்கப்பட்டிருக்கும்போதும் காட்டப்படும்"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"முன்னுரிமை"</string>
<string name="no_shortcut" msgid="8257177117568230126">"உரையாடல் அம்சங்களை <xliff:g id="APP_NAME">%1$s</xliff:g> ஆதரிக்காது"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"இந்த அறிவிப்புகளை மாற்ற இயலாது."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"அழைப்பு அறிவிப்புகளை மாற்ற முடியாது."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"இந்த அறிவுப்புக் குழுக்களை இங்கே உள்ளமைக்க இயலாது"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"கால்குலேட்டர்"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"தொந்தரவு செய்ய வேண்டாம்"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ஒலியளவுப் பொத்தான்களுக்கான ஷார்ட்கட்"</string>
<string name="battery" msgid="769686279459897127">"பேட்டரி"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"சிஸ்டம் ஆப்ஸ்"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"பல வேலைகளைச் செய்தல்"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"திரைப் பிரிப்பு"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"மாற்றுத்திறன் வசதி"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"உள்ளீடு"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ஆப்ஸ் ஷார்ட்கட்கள்"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"தற்போதைய ஆப்ஸ்"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"சமீபத்தில் பயன்படுத்திய ஆப்ஸுக்கான சைகை பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"சமீபத்திய ஆப்ஸைப் பார்க்க, உங்கள் டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ஆப்ஸுக்கிடையில் மாறுங்கள்"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"அருமை!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"ஆப்ஸுக்கிடையில் மாறும் சைகைப் பயிற்சியை முடித்துவிட்டீர்கள்."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"அனைத்து ஆப்ஸையும் காட்டு"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"உங்கள் கீபோர்டில் ஆக்‌ஷன் பட்டனை அழுத்தவும்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 404e5a1308f4..c439e00b24a1 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"లాక్ స్క్రీన్ విడ్జెట్‌లు"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"విడ్జెట్‌ను ఉపయోగించి యాప్‌ను తెరవడానికి, ఇది మీరేనని వెరిఫై చేయాల్సి ఉంటుంది. అలాగే, మీ టాబ్లెట్ లాక్ చేసి ఉన్నప్పటికీ, ఎవరైనా వాటిని చూడగలరని గుర్తుంచుకోండి. కొన్ని విడ్జెట్‌లు మీ లాక్ స్క్రీన్‌కు తగినవి కాకపోవచ్చు, వాటిని ఇక్కడ జోడించడం సురక్షితం కాకపోవచ్చు."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"అర్థమైంది"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"విడ్జెట్‌లు"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"విడ్జెట్‌ల\" షార్ట్‌కట్‌ను జోడించడానికి, సెట్టింగ్‌లలో \"లాక్ స్క్రీన్‌లో విడ్జెట్‌లను చూపండి\" అనే ఆప్షన్‌ను ఎనేబుల్ చేసినట్లు నిర్ధారించుకోండి."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"సెట్టింగ్‌లు"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"స్క్రీన్ సేవర్ బటన్‌ను చూపండి"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"హబ్ మోడ్‌ను అన్వేషించండి"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"ఛార్జింగ్ అయ్యే సమయంలో మీకు ఇష్టమైన విడ్జెట్‌లను, స్క్రీన్ సేవర్‌లను యాక్సెస్ చేయండి."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"ప్రారంభించండి"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"వినియోగదారుని మార్చు"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"పుల్‌డౌన్ మెనూ"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్‌లోని అన్ని యాప్‌లు మరియు డేటా తొలగించబడతాయి."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"అప్‌డేట్ చేస్తోంది"</string>
<string name="status_bar_work" msgid="5238641949837091056">"ఆఫీస్ ప్రొఫైల్‌"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"విమానం మోడ్"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"తల్లిదండ్రుల కంట్రోల్స్"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"మీరు <xliff:g id="WHEN">%1$s</xliff:g> సెట్ చేసిన మీ తర్వాత అలారం మీకు వినిపించదు"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>కి"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>కి"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"సంభాషణ నోటిఫికేషన్‌ల ఎగువున, లాక్ స్క్రీన్‌లో ప్రొఫైల్ ఫోటో‌గా చూపిస్తుంది, బబుల్‌గా కనిపిస్తుంది, \'అంతరాయం కలిగించవద్దు\'ను అంతరాయం కలిగిస్తుంది"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ప్రాధాన్యత"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> సంభాషణ ఫీచర్‌లను సపోర్ట్ చేయదు"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ఈ నోటిఫికేషన్‌లను ఎడిట్ చేయడం వీలుపడదు."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"కాల్ నోటిఫికేషన్‌లను ఎడిట్ చేయడం సాధ్యం కాదు."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ఈ నోటిఫికేషన్‌ల గ్రూప్‌ను ఇక్కడ కాన్ఫిగర్ చేయలేము"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"క్యాలిక్యులేటర్"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"అంతరాయం కలిగించవద్దు"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"వాల్యూమ్ బటన్‌ల షార్ట్‌కట్"</string>
<string name="battery" msgid="769686279459897127">"బ్యాటరీ"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"సిస్టమ్ యాప్‌లు"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"మల్టీ-టాస్కింగ్"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"స్ప్లిట్ స్క్రీన్"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"యాక్సెసిబిలిటీ"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ఇన్‌పుట్"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"యాప్ షార్ట్‌కట్‌లు"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"ప్రస్తుత యాప్"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ఇటీవలి యాప్‌లను చూడడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్‌ను మీరు పూర్తి చేశారు."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ఇటీవలి యాప్‌లను చూడటానికి, మీ టచ్‌ప్యాడ్‌లో మూడు వేళ్లను ఉపయోగించి పైకి స్వైప్ చేసి, హోల్డ్ చేయండి"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"యాప్‌ల మధ్య మారండి"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"మీ టచ్‌ప్యాడ్‌లో నాలుగు వేళ్లను ఉపయోగించి కుడి వైపునకు స్వైప్ చేయండి"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"చక్కగా పూర్తి చేశారు!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"మీరు యాప్‌ల మధ్య మారేందుకు సంజ్ఞను పూర్తి చేశారు."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"యాప్‌ల మధ్య మారేందుకు మీ టచ్‌ప్యాడ్‌లో నాలుగు వేళ్లను ఉపయోగించి కుడి వైపునకు స్వైప్ చేయండి"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"అన్ని యాప్‌లను చూడండి"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"మీ కీబోర్డ్‌లో యాక్షన్ కీని నొక్కండి"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"చక్కగా చేశారు!"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index c67852bd826a..7eef44924533 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"วิดเจ็ตในหน้าจอล็อก"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"หากต้องการเปิดแอปโดยใช้วิดเจ็ต คุณจะต้องยืนยันตัวตนของคุณ นอกจากนี้ โปรดทราบว่าผู้อื่นจะดูวิดเจ็ตเหล่านี้ได้แม้ว่าแท็บเล็ตจะล็อกอยู่ก็ตาม วิดเจ็ตบางอย่างอาจไม่ได้มีไว้สำหรับหน้าจอล็อกของคุณ และอาจไม่ปลอดภัยที่จะเพิ่มที่นี่"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"รับทราบ"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"วิดเจ็ต"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"หากต้องการเพิ่มทางลัด \"วิดเจ็ต\" โปรดตรวจสอบว่าได้เปิดใช้ \"แสดงวิดเจ็ตในหน้าจอล็อก\" แล้วในการตั้งค่า"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"การตั้งค่า"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"ปุ่มแสดงภาพพักหน้าจอ"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"สำรวจโหมดฮับ"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"เข้าถึงวิดเจ็ตและภาพพักหน้าจอโปรดขณะชาร์จ"</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"มาเริ่มกันเลย"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"สลับผู้ใช้"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"เมนูแบบเลื่อนลง"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"กำลังอัปเดต"</string>
<string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"การควบคุมโดยผู้ปกครอง"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"เวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"ในวันที่ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,8 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"แสดงที่ด้านบนของการแจ้งเตือนการสนทนาและเป็นรูปโปรไฟล์บนหน้าจอล็อก ปรากฏเป็นบับเบิล แสดงในโหมดห้ามรบกวน"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"สำคัญ"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่รองรับฟีเจอร์การสนทนา"</string>
+ <string name="notification_inline_dismiss" msgid="88423586921134258">"ปิด"</string>
+ <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"ไม่ต้องแสดงอีก"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"แก้ไขการแจ้งเตือนเหล่านี้ไม่ได้"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"แก้ไขการแจ้งเตือนสายเรียกเข้าไม่ได้"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"การแจ้งเตือนกลุ่มนี้กำหนดค่าที่นี่ไม่ได้"</string>
@@ -912,6 +913,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ปฏิทิน"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"เครื่องคิดเลข"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"แผนที่"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ห้ามรบกวน"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ทางลัดปุ่มปรับระดับเสียง"</string>
<string name="battery" msgid="769686279459897127">"แบตเตอรี่"</string>
@@ -1432,8 +1443,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"แอประบบ"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"การทํางานหลายอย่างพร้อมกัน"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"แยกหน้าจอ"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"การช่วยเหลือพิเศษ"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"อินพุต"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"แป้นพิมพ์ลัดของแอป"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"แอปปัจจุบัน"</string>
@@ -1497,12 +1507,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"คุณทำท่าทางสัมผัสเพื่อดูแอปล่าสุดสำเร็จแล้ว"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"หากต้องการดูแอปล่าสุด ให้ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้บนทัชแพด"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"เปลี่ยนแอป"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"ใช้ 4 นิ้วปัดไปทางขวาบนทัชแพด"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"เก่งมาก"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"คุณทำท่าทางสัมผัสเพื่อสลับแอปเสร็จแล้ว"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"ใช้ 4 นิ้วปัดไปทางขวาบนทัชแพดเพื่อเปลี่ยนแอป"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"ดูแอปทั้งหมด"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"กดปุ่มดำเนินการบนแป้นพิมพ์"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ยอดเยี่ยม"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index cf2b2f043963..154ba651fffd 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Mga widget ng lock screen"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Para magbukas ng app gamit ang isang widget, kakailanganin mong i-verify na ikaw iyan. Bukod pa rito, tandaang puwedeng tingnan ng kahit na sino ang mga ito, kahit na naka-lock ang iyong tablet. Posibleng hindi para sa iyong lock screen ang ilang widget at posibleng hindi ligtas ang mga ito na idagdag dito."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Mga Widget"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para idagdag ang shortcut na \"Mga Widget,\" tiyaking naka-enable ang \"Ipakita ang mga widget sa lock screen\" sa mga setting."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Mga Setting"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Button na ipakita ang screensaver"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"I-explore ang hub mode"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"I-access ang mga paborito mong widget at screen saver habang nagcha-charge."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Tara na"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Magpalit ng user"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ina-update"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Profile sa trabaho"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Parental controls"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Hindi mo maririnig ang iyong susunod na alarm ng <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"ng <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"sa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Makikita sa itaas ng mga notification ng pag-uusap at bilang larawan sa profile sa lock screen, lumalabas bilang bubble, naaabala ang Huwag Istorbohin"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priyoridad"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Hindi sinusuportahan ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang mga feature ng pag-uusap"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Hindi puwedeng baguhin ang mga notification na ito."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Hindi mabago ang mga notification ng tawag."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Hindi mako-configure dito ang pangkat na ito ng mga notification"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mga mapa"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Huwag Istorbohin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Shortcut ng mga button ng volume"</string>
<string name="battery" msgid="769686279459897127">"Baterya"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Mga system app"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Pag-multitask"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Split screen"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Accessibility"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Input"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Mga shortcut ng app"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Kasalukuyang App"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Nakumpleto mo ang galaw sa pag-view ng mga kamakailang app."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Para tingnan ang mga kamakailang app, mag-swipe pataas at i-hold gamit ang tatlong daliri sa iyong touchpad"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Lumipat ng app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Mag-swipe pakanan gamit ang apat na daliri sa iyong touchpad"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Magaling!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Nakumpleto mo na ang galaw para magpalipat-lipat sa mga app."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Mag-swipe pakanan gamit ang apat na daliri sa iyong touchpad para lumipat ng app"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Tingnan ang lahat ng app"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pindutin ang action key sa iyong keyboard"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Magaling!"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 8cd9eb36d180..d532bef9bf07 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kilit ekranı widget\'ları"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Widget kullanarak bir uygulamayı açmak için kimliğinizi doğrulamanız gerekir. Ayrıca, tabletiniz kilitliyken bile widget\'ların herkes tarafından görüntülenebileceğini unutmayın. Bazı widget\'lar kilit ekranınız için tasarlanmamış olabileceğinden buraya eklenmeleri güvenli olmayabilir."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Anladım"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widget\'lar"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Widget\'lar\" kısayolunu eklemek için ayarlarda \"Widget\'ları kilit ekranında göster\" seçeneğinin etkinleştirildiğinden emin olun."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ayarlar"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Ekran koruyucuyu göster düğmesi"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştirme"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"açılır menü"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Güncelleniyor"</string>
<string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Uçak modu"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Ebeveyn denetimleri"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız"</string>
<string name="alarm_template" msgid="2234991538018805736">"saat: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"gün ve saat: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Görüşme bildirimlerinin üstünde ve kilit ekranında profil resmi olarak gösterilir, baloncuk olarak görünür, Rahatsız Etmeyin\'i kesintiye uğratır"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Öncelikli"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>, sohbet özelliklerini desteklemiyor"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirimler değiştirilemez."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Arama bildirimleri değiştirilemez."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Bu bildirim grubu burada yapılandırılamaz"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Takvim"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Hesap Makinesi"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Haritalar"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Rahatsız Etmeyin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Ses düğmeleri kısayolu"</string>
<string name="battery" msgid="769686279459897127">"Pil"</string>
@@ -1497,11 +1513,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Son uygulamaları görüntüleme hareketini tamamladınız."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Son kullanılan uygulamaları görüntülemek için dokunmatik alanda üç parmağınızla yukarı kaydırıp basılı tutun"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Uygulamalar arasında geçiş yapma"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Tebrikler!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Uygulamalar arasında geçiş yapma hareketini tamamladınız."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Tüm uygulamaları göster"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Klavyenizde eylem tuşuna basın"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index bd877f3a4c7c..c3a01f587145 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Віджети для заблокованого екрана"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Щоб відкрити додаток за допомогою віджета, вам потрібно буде підтвердити особу. Пам’ятайте також, що бачити віджети можуть усі, навіть коли планшет заблоковано. Можливо, деякі віджети не призначені для заблокованого екрана, і додавати їх на нього може бути небезпечно."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Віджети"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Щоб додати ярлик \"Віджети\", переконайтеся, що в налаштуваннях увімкнено опцію \"Показувати віджети на заблокованому екрані\"."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Налаштування"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Кнопка \"Показати заставку\""</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Змінити користувача"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"спадне меню"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усі додатки й дані з цього сеансу буде видалено."</string>
@@ -802,6 +805,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"З’являється вгорі сповіщень про розмови і як зображення профілю на заблокованому екрані, відображається як спливаючий чат, перериває режим \"Не турбувати\""</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Пріоритет"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не підтримує функції розмов"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Ці сповіщення не можна змінити."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Сповіщення про виклик не можна змінити."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Цю групу сповіщень не можна налаштувати тут"</string>
@@ -912,6 +919,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калькулятор"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карти"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не турбувати"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Кнопки гучності на корпусі"</string>
<string name="battery" msgid="769686279459897127">"Акумулятор"</string>
@@ -1497,11 +1514,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ви виконали жест для перегляду нещодавно відкритих додатків."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Щоб переглянути останні додатки, проведіть трьома пальцями вгору й утримуйте їх на сенсорній панелі"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Перемикання між додатками"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Чудово!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Ви виконали жест перемикання додатків."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Переглянути всі додатки"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Натисніть клавішу дії на клавіатурі"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d3900f2be29f..bbde3351188e 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"مقفل اسکرین کے ویجیٹس"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"ویجیٹ کے ذریعے ایپ کھولنے کے لیے آپ کو تصدیق کرنی ہوگی کہ یہ آپ ہی ہیں۔ نیز، ذہن میں رکھیں کہ کوئی بھی انہیں دیکھ سکتا ہے، یہاں تک کہ جب آپ کا ٹیبلیٹ مقفل ہو۔ ہو سکتا ہے کچھ ویجٹس آپ کی لاک اسکرین کے لیے نہ بنائے گئے ہوں اور یہاں شامل کرنا غیر محفوظ ہو سکتا ہے۔"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"سمجھ آ گئی"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ویجیٹس"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"ویجیٹس\" شارٹ کٹ شامل کرنے کے لیے، یقینی بنائیں کہ \"مقفل اسکرین پر ویجیٹس دکھائیں\" ترتیبات میں فعال ہے۔"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ترتیبات"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"اسکرین سیور بٹن دکھائیں"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"ہب موڈ دریافت کریں"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"چارج کرتے وقت اپنے پسندیدہ ویجیٹس اور اسکرین سیورز تک رسائی حاصل کریں۔"</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"آئیے شروع کریں"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"صارف سوئچ کریں"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"پل ڈاؤن مینیو"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"اس سیشن میں موجود سبھی ایپس اور ڈیٹا کو حذف کر دیا جائے گا۔"</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"اپ ڈیٹ ہو رہا ہے"</string>
<string name="status_bar_work" msgid="5238641949837091056">"دفتری پروفائل"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"ہوائی جہاز وضع"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"پیرنٹل کنٹرولز"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"آپ کو <xliff:g id="WHEN">%1$s</xliff:g> بجے اپنا اگلا الارم سنائی نہیں دے گا"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> بجے"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> بجے"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"یہ گفتگو کی اطلاعات کے اوپری حصّے پر اور مقفل اسکرین پر پروفائل کی تصویر کے بطور دکھائی دیتا ہے، بلبلے کے بطور ظاہر ہوتا ہے، \'ڈسٹرب نہ کریں\' میں مداخلت کرتا ہے"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ترجیح"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ گفتگو کی خصوصیات کو سپورٹ نہیں کرتی ہے"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ان اطلاعات کی ترمیم نہیں کی جا سکتی۔"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"کال کی اطلاعات میں ترمیم نہیں کی جا سکتی۔"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"اطلاعات کے اس گروپ کو یہاں کنفیگر نہیں کیا جا سکتا"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"کیلنڈر"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"کیلکولیٹر"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ڈسٹرب نہ کریں"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"والیوم بٹنز کے شارٹ کٹ"</string>
<string name="battery" msgid="769686279459897127">"بیٹری"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"سسٹم ایپس"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ملٹی ٹاسکنگ"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"اسپلٹ اسکرین"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"ایکسیسبیلٹی"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"ان پٹ"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"ایپ شارٹ کٹس"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"موجودہ ایپ"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"آپ نے حالیہ ایپس دیکھیں کا اشارہ مکمل کر لیا ہے۔"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"حالیہ ایپس دیکھنے کے لیے، اپنے ٹچ پیڈ پر تین انگلیوں کی مدد سے اوپر کی طرف سوائپ کریں اور دبائے رکھیں"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"ایپس سوئچ کریں"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"اپنے ٹچ پیڈ پر چار انگلیوں کا استعمال کرتے ہوئے بائیں طرف سوائپ کریں"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"بہترین!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"آپ نے ایپس کے مابین سوئچ کرنے کا اشارہ مکمل کر لیا۔"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"ایپس سوئچ کرنے کے لیے اپنے ٹچ پیڈ پر چار انگلیوں کا استعمال کرتے ہوئے بائیں طرف سوائپ کریں"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"سبھی ایپس دیکھیں"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"اپنے کی بورڈ پر ایکشن کلید دبائیں"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"بہت خوب!"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 7006abb34b99..ea4a7c7cad3a 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Ekran qulfi vidjetlari"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ilovani vidjet orqali ochish uchun shaxsingizni tasdiqlashingiz kerak. Shuningdek, planshet qulflanganda ham bu axborotlar hammaga koʻrinishini unutmang. Ayrim vidjetlar ekran qulfiga moslanmagan va ularni bu yerda chiqarish xavfli boʻlishi mumkin."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"OK"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidjetlar"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"“Vidjetlar” yorligʻini qoʻshish uchun sozlamalarda “Vidjetlarni ekran qulfida chiqarish” yoqilganini tekshiring."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Sozlamalar"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Ekran lavhasi tugmasini chiqarish"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"Hub rejimi bilan tanishing"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"Quvvatlash paytida sevimli vidjetlar va ekran lavhalaridan foydalaning."</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"Boshlash"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Foydalanuvchini almashtirish"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"tortib tushiriladigan menyu"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ushbu seansdagi barcha ilovalar va ma’lumotlar o‘chirib tashlanadi."</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Yangilanmoqda"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Ish profili"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Parvoz rejimi"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Ota-ona nazorati"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Keyingi signal (<xliff:g id="WHEN">%1$s</xliff:g>) chalinmaydi"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,8 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Suhbat bildirishnomalari tepasida va ekran qulfida profil rasmi sifatida chiqariladi, bulutcha sifatida chiqadi, Bezovta qilinmasin rejimini bekor qiladi"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Muhim"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasida suhbat funksiyalari ishlamaydi"</string>
+ <string name="notification_inline_dismiss" msgid="88423586921134258">"Yopish"</string>
+ <string name="notification_inline_disable_promotion" msgid="6880961831026048166">"Boshqa chiqmasin"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirishnomalarni tahrirlash imkonsiz."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Chaqiruv bildirishnomalarini tahrirlash imkonsiz."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ushbu bildirishnomalar guruhi bu yerda sozlanmaydi"</string>
@@ -912,6 +913,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Taqvim"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulyator"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Xaritalar"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Bezovta qilinmasin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Ovoz balandligini boshqarish tugmalari"</string>
<string name="battery" msgid="769686279459897127">"Batareya"</string>
@@ -1432,8 +1443,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Tizim ilovalari"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multi-vazifalilik"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Ekranni ikkiga ajratish"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Qulaylik"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Kiritish"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Ilova yorliqlari"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Joriy ilova"</string>
@@ -1497,12 +1507,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Oxirgi ilovalarni koʻrish ishorasini tugalladingiz."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Oxirgi ochilgan ilovalarni koʻrish uchun sensorli panelda uchta barmoq bilan tepega surib, ushlab turing"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Ilovalarni almashtirish"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"Sensorli panelda toʻrtta barmoq bilan oʻngga suring"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Barakalla!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Ilovalarni almashtirish darsini tamomladingiz."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"Ilovalarni almashtirish uchun sensorli panelda toʻrtta barmoq bilan oʻngga suring"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Barcha ilovalarni koʻrish"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Klaviaturadagi amal tugmasini bosing"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Barakalla!"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 18857426db84..5380afa883c5 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Tiện ích trên màn hình khoá"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Để dùng tiện ích mở một ứng dụng, bạn cần xác minh danh tính của mình. Ngoài ra, hãy lưu ý rằng bất kỳ ai cũng có thể xem các tiện ích này, ngay cả khi máy tính bảng của bạn được khoá. Một số tiện ích có thể không dành cho màn hình khoá và không an toàn khi thêm vào đây."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Tôi hiểu"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Tiện ích"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Để thêm phím tắt \"Tiện ích\", hãy nhớ bật tuỳ chọn \"Hiện tiện ích trên màn hình khoá\" trong phần cài đặt."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Cài đặt"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Hiện nút trình bảo vệ màn hình"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Chuyển đổi người dùng"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"trình đơn kéo xuống"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tất cả ứng dụng và dữ liệu trong phiên này sẽ bị xóa."</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Đang cập nhật"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Hồ sơ công việc"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Chế độ trên máy bay"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Chế độ kiểm soát của cha mẹ"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Bạn sẽ không nghe thấy chuông báo tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình"</string>
<string name="alarm_template" msgid="2234991538018805736">"lúc <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"vào <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Hiện ở đầu phần thông báo cuộc trò chuyện và ở dạng ảnh hồ sơ trên màn hình khóa, xuất hiện ở dạng bong bóng, làm gián đoạn chế độ Không làm phiền"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Mức độ ưu tiên"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> không hỗ trợ các tính năng trò chuyện"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Không thể sửa đổi các thông báo này."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Không thể sửa đổi các thông báo cuộc gọi."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Không thể định cấu hình nhóm thông báo này tại đây"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Lịch"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Máy tính"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Bản đồ"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Không làm phiền"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Phím tắt các nút âm lượng"</string>
<string name="battery" msgid="769686279459897127">"Pin"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Ứng dụng hệ thống"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Đa nhiệm"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Chia đôi màn hình"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Hỗ trợ tiếp cận"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Phương thức nhập"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Phím tắt cho ứng dụng"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Ứng dụng hiện tại"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Bạn đã hoàn tất cử chỉ xem ứng dụng gần đây."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Để xem các ứng dụng gần đây, hãy dùng 3 ngón tay vuốt lên và giữ trên bàn di chuột"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Chuyển đổi ứng dụng"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Tuyệt vời!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Bạn đã thực hiện xong cử chỉ chuyển đổi ứng dụng."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Xem tất cả các ứng dụng"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Nhấn phím hành động trên bàn phím"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 53c825baab02..4b29fb6865f7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -535,10 +535,10 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"锁屏微件"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"若要使用微件打开应用,您需要验证是您本人在操作。另外请注意,任何人都可以查看此类微件,即使您的平板电脑已锁定。有些微件可能不适合显示在锁定的屏幕中,因此添加到这里可能不安全。"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"知道了"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"微件"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"如要添加“微件”快捷方式,请确保已在设置中启用“在锁屏状态下显示微件”。"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"设置"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"“显示屏保”按钮"</string>
+ <string name="hub_onboarding_bottom_sheet_title" msgid="162092881395529947">"探索基座接入模式"</string>
+ <string name="hub_onboarding_bottom_sheet_text" msgid="8589816797970240544">"充电时访问您喜爱的微件和屏保。"</string>
+ <string name="hub_onboarding_bottom_sheet_action_button" msgid="6161983690157872829">"现在就试试吧"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切换用户"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉菜单"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
@@ -750,8 +750,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"正在更新"</string>
<string name="status_bar_work" msgid="5238641949837091056">"工作资料"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飞行模式"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"家长控制"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"您在<xliff:g id="WHEN">%1$s</xliff:g>将不会听到下次闹钟响铃"</string>
<string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +801,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以气泡形式显示在对话通知顶部(屏幕锁定时显示为个人资料照片),并且会中断勿扰模式"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"优先"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>不支持对话功能"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"无法修改这些通知。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"无法修改来电通知。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"您无法在此处配置这组通知"</string>
@@ -912,6 +915,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"日历"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"计算器"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"地图"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"勿扰"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量按钮快捷键"</string>
<string name="battery" msgid="769686279459897127">"电池"</string>
@@ -1432,8 +1445,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"系统应用"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"多任务处理"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"分屏"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"无障碍"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"输入"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"应用快捷键"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"当前应用"</string>
@@ -1497,12 +1509,10 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"您已完成“查看最近用过的应用”的手势教程。"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"如需查看最近用过的应用,请用三根手指在触控板上向上滑动并按住"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"切换应用"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
- <skip />
+ <string name="touchpad_switch_apps_gesture_guidance" msgid="2554844933805502538">"在触控板上用四根手指向右滑动"</string>
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"太棒了!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"您完成了应用切换手势教程。"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
- <skip />
+ <string name="touchpad_switch_gesture_error_body" msgid="5895231916964677918">"在触控板上用四根手指向右滑动可切换应用"</string>
<string name="tutorial_action_key_title" msgid="8172535792469008169">"查看所有应用"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"按键盘上的快捷操作按键"</string>
<string name="tutorial_action_key_success_title" msgid="2371827347071979571">"非常棒!"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index aa539d699378..1605840fe463 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"上鎖畫面小工具"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"如要使用小工具開啟應用程式,系統會要求你驗證身分。請注意,所有人都能查看小工具,即使平板電腦已鎖定亦然。部分小工具可能不適用於上鎖畫面,新增至這裡可能會有安全疑慮。"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"知道了"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"小工具"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"如要新增「小工具」捷徑,請確保在設定中已啟用「在上鎖畫面顯示小工具」。"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"設定"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"顯示螢幕保護程式按鈕"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"正在更新"</string>
<string name="status_bar_work" msgid="5238641949837091056">"工作設定檔"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飛行模式"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"家長監控設定"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"你不會<xliff:g id="WHEN">%1$s</xliff:g>聽到鬧鐘"</string>
<string name="alarm_template" msgid="2234991538018805736">"在 <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"在<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以對話氣泡形式顯示在對話通知頂部 (在上鎖畫面會顯示為個人檔案相片),並會中斷「請勿打擾」模式"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
<string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"無法修改這些通知。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"無法修改通話通知。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"無法在此設定這組通知"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"日曆"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"計算機"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"地圖"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"請勿騷擾"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量按鈕快速鍵"</string>
<string name="battery" msgid="769686279459897127">"電池"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"系統應用程式"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"多工處理"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"分割螢幕"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"無障礙功能"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"輸入"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"應用程式捷徑"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"目前的應用程式"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"你已完成「查看最近使用的應用程式」手勢的教學課程。"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"如要查看最近使用的應用程式,請用三隻手指在觸控板上向上滑動並按住"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"切換應用程式"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"做得好!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"你已完成「應用程式切換手勢」的教學課程。"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"查看所有應用程式"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"按下鍵盤上的快捷操作鍵"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2d6ac8d43442..cbdb641bf76f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -535,10 +535,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"螢幕鎖定小工具"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"如要使用小工具開啟應用程式,需先驗證身分。請留意,即使平板電腦已鎖定,所有人都還是能查看小工具。某些小工具可能不適用於螢幕鎖定畫面,新增到此可能會有安全疑慮。"</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"我知道了"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"小工具"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"如要新增「小工具」捷徑,請務必前往設定啟用「在螢幕鎖定畫面上顯示小工具」。"</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"設定"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"顯示螢幕保護程式按鈕"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會刪除。"</string>
@@ -750,8 +753,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"更新中"</string>
<string name="status_bar_work" msgid="5238641949837091056">"工作資料夾"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"飛航模式"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"家長監護"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"你不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g> 的鬧鐘"</string>
<string name="alarm_template" msgid="2234991538018805736">"於<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"於<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -802,6 +804,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以對話框的形式顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片),並會中斷「零打擾」模式"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
<string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"無法修改這些通知。"</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"無法修改來電通知。"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"無法在這裡設定這個通知群組"</string>
@@ -912,6 +918,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"日曆"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"計算機"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"地圖"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"零打擾"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量鍵快速鍵"</string>
<string name="battery" msgid="769686279459897127">"電池"</string>
@@ -1432,8 +1448,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"系統應用程式"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"多工處理"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"分割畫面"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"無障礙功能"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"輸入"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"應用程式捷徑"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"目前的應用程式"</string>
@@ -1497,11 +1512,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"你已完成「查看最近使用的應用程式」手勢教學課程。"</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"如要查看最近使用的應用程式,請在觸控板上用三指向上滑動並按住"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"切換應用程式"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"太棒了!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"你已完成應用程式切換手勢的教學課程。"</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"查看所有應用程式"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"按下鍵盤上的快捷操作鍵"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a210ca37214f..16d223d858df 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -537,10 +537,13 @@
<string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Amawijethi wesikrini esikhiyiwe"</string>
<string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Ukuze uvule i-app usebenzisa iwijethi, uzodinga ukuqinisekisa ukuthi nguwe. Futhi, khumbula ukuthi noma ubani angakwazi ukuzibuka, nanoma ithebhulethi yakho ikhiyiwe. Amanye amawijethi kungenzeka abengahloselwe ukukhiya isikrini sakho futhi kungenzeka awaphephile ukuthi angafakwa lapha."</string>
<string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"Ngiyezwa"</string>
- <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Amawijethi"</string>
- <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Ukuze ufake isinqamuleli esithi \"Amawijethi\", qinisekisa ukuthi okuthi \"Bonisa amawijethi esikrinini sokukhiya\" kunikwe amandla kumasethingi."</string>
- <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Amasethingi"</string>
<string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Bonisa inkinobho yesigcini sesikrini"</string>
+ <!-- no translation found for hub_onboarding_bottom_sheet_title (162092881395529947) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_text (8589816797970240544) -->
+ <skip />
+ <!-- no translation found for hub_onboarding_bottom_sheet_action_button (6161983690157872829) -->
+ <skip />
<string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Shintsha umsebenzisi"</string>
<string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"imenyu yokudonsela phansi"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wonke ama-app nedatha kulesi sikhathi azosuswa."</string>
@@ -752,8 +755,7 @@
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Iyabuyekeza"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Iphrofayela yomsebenzi"</string>
<string name="status_bar_airplane" msgid="4848702508684541009">"Imodi yendiza"</string>
- <!-- no translation found for status_bar_supervision (6735015942701134125) -->
- <skip />
+ <string name="status_bar_supervision" msgid="6735015942701134125">"Izilawuli zomzali"</string>
<string name="zen_alarm_warning" msgid="7844303238486849503">"Ngeke uzwe i-alamu yakho elandelayo ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template" msgid="2234991538018805736">"ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"nge-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -804,6 +806,10 @@
<string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Ivela phezu kwezaziso zengxoxo futhi njengesithombe sephrofayela esikrinini sokukhiya, ivela njengebhamuza, ukuphazamisa okuthi Ungaphazamisi"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Okubalulekile"</string>
<string name="no_shortcut" msgid="8257177117568230126">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayisekeli izici zengxoxo"</string>
+ <!-- no translation found for notification_inline_dismiss (88423586921134258) -->
+ <skip />
+ <!-- no translation found for notification_inline_disable_promotion (6880961831026048166) -->
+ <skip />
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Lezi zaziso azikwazi ukushintshwa."</string>
<string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Izaziso zekholi azikwazi ukushintshwa."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Leli qembu lezaziso alikwazi ukulungiselelwa lapha"</string>
@@ -914,6 +920,16 @@
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Ikhalenda"</string>
<string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Isibali"</string>
<string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"I-Maps"</string>
+ <!-- no translation found for group_accessibility_toggle_bounce_keys (4183584952493519179) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_mouse_keys (534757719357514361) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_sticky_keys (7722214637652104184) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_slow_keys (8569881436531795062) -->
+ <skip />
+ <!-- no translation found for group_accessibility_toggle_voice_access (5436708239015479017) -->
+ <skip />
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ungaphazamisi"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Izinqamuleli zezinkinobho zevolomu"</string>
<string name="battery" msgid="769686279459897127">"Ibhethri"</string>
@@ -1434,8 +1450,7 @@
<string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Ama-app esistimu"</string>
<string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Ukwenza imisebenzi eminingi"</string>
<string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Hlukanisa isikrini"</string>
- <!-- no translation found for shortcutHelper_category_accessibility (8068337792277570938) -->
- <skip />
+ <string name="shortcutHelper_category_accessibility" msgid="8068337792277570938">"Ukufinyeleleka"</string>
<string name="shortcut_helper_category_input" msgid="8674018654124839566">"Okokufaka"</string>
<string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Izinqamuleli Zohlelo lokusebenza"</string>
<string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"I-App yamanje"</string>
@@ -1499,11 +1514,11 @@
<string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Uqedele ukubuka ukuthinta kwama-app akamuva."</string>
<string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Ukuze ubuke ama-app akamuva, swayiphela phezulu futhi ubambe usebenzisa iminwe emithathu kuphedi yakho yokuthinta"</string>
<string name="touchpad_switch_apps_gesture_action_title" msgid="6835222344612924512">"Shintsha ama-app"</string>
- <!-- no translation found for touchpad_switch_apps_gesture_guidance (2751565200937541667) -->
+ <!-- no translation found for touchpad_switch_apps_gesture_guidance (2554844933805502538) -->
<skip />
<string name="touchpad_switch_apps_gesture_success_title" msgid="4894947244328032458">"Umsebenzi omuhle!"</string>
<string name="touchpad_switch_apps_gesture_success_body" msgid="8151089866035126312">"Ukuqedile ukuthinta kokushintsha ama-app."</string>
- <!-- no translation found for touchpad_switch_gesture_error_body (5508381152326379652) -->
+ <!-- no translation found for touchpad_switch_gesture_error_body (5895231916964677918) -->
<skip />
<string name="tutorial_action_key_title" msgid="8172535792469008169">"Buka wonke ama-app"</string>
<string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Cindezela inkinobho yokufinyelela kukhibhodi yakho"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 36ede64f91d9..015e0e83e57d 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -24,6 +24,7 @@
<color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
<color name="qs_detail_button_white">#B3FFFFFF</color><!-- 70% white -->
<color name="status_bar_clock_color">#FFFFFFFF</color>
+ <color name="shade_header_text_color">#FFFFFFFF</color>
<color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black -->
<color name="status_bar_icons_hover_color_light">#38FFFFFF</color> <!-- 22% white -->
<color name="status_bar_icons_hover_color_dark">#38000000</color> <!-- 22% black -->
@@ -260,4 +261,8 @@
<!-- Rear Display Education -->
<color name="rear_display_overlay_animation_background_color">#1E1B17</color>
<color name="rear_display_overlay_dialog_background_color">#1E1B17</color>
+
+ <!-- Low light Dream -->
+ <color name="low_light_clock_background_color">#000000</color>
+ <color name="low_light_clock_text_color">#CCCCCC</color>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 724a12c12490..42d66e23feb9 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1614,6 +1614,18 @@
<!-- GLANCEABLE_HUB -> DREAMING transition: Amount to shift dream overlay on entering -->
<dimen name="hub_to_dreaming_transition_dream_overlay_translation_x">824dp</dimen>
+ <!-- Low light clock -->
+ <!-- The text size of the low light clock is intentionally defined in dp to avoid scaling -->
+ <dimen name="low_light_clock_text_size">260dp</dimen>
+ <dimen name="low_light_clock_charging_text_size">14sp</dimen>
+ <dimen name="low_light_clock_charging_text_min_height">48dp</dimen>
+ <integer name="low_light_clock_charging_text_font_weight">500</integer>
+
+ <dimen name="low_light_clock_translate_animation_offset">40dp</dimen>
+ <integer name="low_light_clock_translate_animation_duration_ms">1167</integer>
+ <integer name="low_light_clock_alpha_animation_in_start_delay_ms">233</integer>
+ <integer name="low_light_clock_alpha_animation_duration_ms">250</integer>
+
<!-- Distance that the full shade transition takes in order for media to fully transition to
the shade -->
<dimen name="lockscreen_shade_media_transition_distance">120dp</dimen>
@@ -2138,4 +2150,8 @@
<dimen name="volume_panel_slice_vertical_padding">8dp</dimen>
<dimen name="volume_panel_slice_horizontal_padding">24dp</dimen>
<!-- Volume end -->
+
+ <!-- Gradient color wallpaper start -->
+ <dimen name="gradient_color_wallpaper_center_offset">128dp</dimen>
+ <!-- Gradient color wallpaper end -->
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 64367ef79856..3b89e9c42c93 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2384,6 +2384,12 @@
<string name="group_accessibility_toggle_slow_keys">Toggle slow keys</string>
<!-- User visible title for the keyboard shortcut that toggles Voice Access. [CHAR LIMIT=70] -->
<string name="group_accessibility_toggle_voice_access">Toggle Voice Access</string>
+ <!-- User visible title for the keyboard shortcut that toggles Talkback. [CHAR LIMIT=70] -->
+ <string name="group_accessibility_toggle_talkback">Toggle Talkback</string>
+ <!-- User visible title for the keyboard shortcut that toggles Magnification. [CHAR LIMIT=70] -->
+ <string name="group_accessibility_toggle_magnification">Toggle Magnification</string>
+ <!-- User visible title for the keyboard shortcut that activates Select to Speak service. [CHAR LIMIT=70] -->
+ <string name="group_accessibility_activate_select_to_speak">Activate Select to Speak</string>
<!-- SysUI Tuner: Label for screen about do not disturb settings [CHAR LIMIT=60] -->
<string name="volume_and_do_not_disturb">Do Not Disturb</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index c95c6dd89353..fa6a41a74ca9 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -176,17 +176,11 @@
<style name="TextAppearance.QS.Status">
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
- <item name="android:textColor">?attr/onSurface</item>
+ <item name="android:textColor">@color/shade_header_text_color</item>
<item name="android:textSize">14sp</item>
<item name="android:letterSpacing">0.01</item>
</style>
- <style name="TextAppearance.QS.Status.Carriers" />
-
- <style name="TextAppearance.QS.Status.Carriers.NoCarrierText">
- <item name="android:textColor">?attr/onSurfaceVariant</item>
- </style>
-
<style name="TextAppearance.QS.Status.Build">
<item name="android:textColor">?attr/onSurfaceVariant</item>
</style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ILauncherProxy.aidl
index 011458859db4..b43ffc530289 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ILauncherProxy.aidl
@@ -24,7 +24,7 @@ import android.view.MotionEvent;
import com.android.systemui.shared.recents.ISystemUiProxy;
// Next ID: 39
-oneway interface IOverviewProxy {
+oneway interface ILauncherProxy {
void onActiveNavBarRegionChanges(in Region activeRegion) = 11;
@@ -140,7 +140,7 @@ oneway interface IOverviewProxy {
void appTransitionPending(boolean pending) = 34;
/**
- * Sent right after OverviewProxy calls unbindService() on the TouchInteractionService.
+ * Sent right after LauncherProxyService calls unbindService() on the TouchInteractionService.
* TouchInteractionService is expected to send the reply once it has finished cleaning up.
*/
void onUnbind(IRemoteCallback reply) = 35;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index e332280bc31a..1f6bea18d53a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -69,10 +69,10 @@ interface ISystemUiProxy {
/**
* Indicates that the given Assist invocation types should be handled by Launcher via
- * OverviewProxy#onAssistantOverrideInvoked and should not be invoked by SystemUI.
+ * LauncherProxy#onAssistantOverrideInvoked and should not be invoked by SystemUI.
*
* @param invocationTypes The invocation types that will henceforth be handled via
- * OverviewProxy (Launcher); other invocation types should be handled by SysUI.
+ * LauncherProxy (Launcher); other invocation types should be handled by SysUI.
*/
oneway void setAssistantOverridesRequested(in int[] invocationTypes) = 53;
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 32a76fb8439a..9ebb15f43307 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
@@ -16,12 +16,12 @@
package com.android.systemui.shared.recents.utilities;
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_VISIBLE;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
+import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
import android.annotation.TargetApi;
-import android.app.StatusBarManager.NavigationHint;
+import android.app.StatusBarManager.NavbarFlags;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
@@ -104,46 +104,46 @@ public class Utilities {
}
/**
- * Gets the updated navigation icon hints, based on the current ones and the given IME state.
+ * Updates the navigation bar state flags with the given IME state.
*
- * @param oldHints current navigation icon hints.
+ * @param oldFlags current navigation bar state flags.
* @param backDisposition the IME back disposition mode. Only takes effect if
* {@code isImeVisible} is {@code true}.
* @param isImeVisible whether the IME is currently visible.
* @param showImeSwitcher whether the IME Switcher button should be shown. Only takes effect if
* {@code isImeVisible} is {@code true}.
*/
- @NavigationHint
- public static int calculateNavigationIconHints(@NavigationHint int oldHints,
+ @NavbarFlags
+ public static int updateNavbarFlagsFromIme(@NavbarFlags int oldFlags,
@BackDispositionMode int backDisposition, boolean isImeVisible,
boolean showImeSwitcher) {
- int hints = oldHints;
+ int flags = oldFlags;
switch (backDisposition) {
case InputMethodService.BACK_DISPOSITION_DEFAULT:
case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS:
case InputMethodService.BACK_DISPOSITION_WILL_DISMISS:
if (isImeVisible) {
- hints |= NAVIGATION_HINT_BACK_ALT;
+ flags |= NAVBAR_BACK_DISMISS_IME;
} else {
- hints &= ~NAVIGATION_HINT_BACK_ALT;
+ flags &= ~NAVBAR_BACK_DISMISS_IME;
}
break;
case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING:
- hints &= ~NAVIGATION_HINT_BACK_ALT;
+ flags &= ~NAVBAR_BACK_DISMISS_IME;
break;
}
if (isImeVisible) {
- hints |= NAVIGATION_HINT_IME_VISIBLE;
+ flags |= NAVBAR_IME_VISIBLE;
} else {
- hints &= ~NAVIGATION_HINT_IME_VISIBLE;
+ flags &= ~NAVBAR_IME_VISIBLE;
}
if (showImeSwitcher && isImeVisible) {
- hints |= NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+ flags |= NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
} else {
- hints &= ~NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+ flags &= ~NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
}
- return hints;
+ return flags;
}
/** @return whether or not {@param context} represents that of a large screen device or not */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 0048fd4d33d3..82ac78c6db15 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -134,8 +134,10 @@ public class QuickStepContract {
public static final long SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING = 1L << 34;
// Communal hub is showing
public static final long SYSUI_STATE_COMMUNAL_HUB_SHOWING = 1L << 35;
- // The back button is adjusted for the IME.
- public static final long SYSUI_STATE_IME_ALT_BACK = 1L << 36;
+ // The back button is visually adjusted to indicate that it will dismiss the IME when pressed.
+ // This only takes effect while the IME is visible. By default, it is set while the IME is
+ // visible, but may be overridden by the backDispositionMode set by the IME.
+ public static final long SYSUI_STATE_BACK_DISMISS_IME = 1L << 36;
// Mask for SystemUiStateFlags to isolate SYSUI_STATE_AWAKE and
// SYSUI_STATE_WAKEFULNESS_TRANSITION, to match WAKEFULNESS_* constants
@@ -187,7 +189,7 @@ public class QuickStepContract {
SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED,
SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING,
SYSUI_STATE_COMMUNAL_HUB_SHOWING,
- SYSUI_STATE_IME_ALT_BACK,
+ SYSUI_STATE_BACK_DISMISS_IME,
})
public @interface SystemUiStateFlags {}
@@ -298,8 +300,8 @@ public class QuickStepContract {
if ((flags & SYSUI_STATE_COMMUNAL_HUB_SHOWING) != 0) {
str.add("communal_hub_showing");
}
- if ((flags & SYSUI_STATE_IME_ALT_BACK) != 0) {
- str.add("ime_alt_back");
+ if ((flags & SYSUI_STATE_BACK_DISMISS_IME) != 0) {
+ str.add("back_dismiss_ime");
}
return str.toString();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index 7f176de547bc..0e9d8fec9717 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -16,6 +16,8 @@
package com.android.keyguard;
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
+
import static com.android.systemui.Flags.pinInputFieldStyledFocusState;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -164,6 +166,8 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
layoutParams.height = (int) getResources().getDimension(
R.dimen.keyguard_pin_field_height);
}
+
+ mPasswordEntry.sendAccessibilityEvent(TYPE_VIEW_FOCUSED);
}
private void setKeyboardBasedFocusOutline(boolean isAnyKeyboardConnected) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
index 641cac51785f..22092dcd2a43 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
@@ -111,7 +111,9 @@ public class KeyguardSecurityViewFlipperController
// Prevent multiple inflations for the same security mode. Instead, add callback to a list
// and then notify each in order when the view is inflated.
- mOnViewInflatedListeners.add(onViewInflatedCallback);
+ synchronized (mOnViewInflatedListeners) {
+ mOnViewInflatedListeners.add(onViewInflatedCallback);
+ }
if (!mSecurityModeInProgress.contains(securityMode)) {
mSecurityModeInProgress.add(securityMode);
asynchronouslyInflateView(securityMode, keyguardSecurityCallback);
@@ -145,10 +147,14 @@ public class KeyguardSecurityViewFlipperController
childController.init();
mChildren.add(childController);
- for (OnViewInflatedCallback callback : mOnViewInflatedListeners) {
+ List<OnViewInflatedCallback> callbacks;
+ synchronized (mOnViewInflatedListeners) {
+ callbacks = new ArrayList<>(mOnViewInflatedListeners);
+ mOnViewInflatedListeners.clear();
+ }
+ for (OnViewInflatedCallback callback : callbacks) {
callback.onViewInflated(childController);
}
- mOnViewInflatedListeners.clear();
// Single bouncer constrains are default
if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)) {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 40c1f0f9895d..4a8e4ed3f6f1 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -39,7 +39,7 @@ import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -129,7 +129,7 @@ public class Dependency {
@Inject Lazy<MetricsLogger> mMetricsLogger;
@Inject Lazy<UiOffloadThread> mUiOffloadThread;
@Inject Lazy<LightBarController> mLightBarController;
- @Inject Lazy<OverviewProxyService> mOverviewProxyService;
+ @Inject Lazy<LauncherProxyService> mLauncherProxyService;
@Inject Lazy<NavigationModeController> mNavBarModeController;
@Inject Lazy<NavigationBarController> mNavigationBarController;
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@@ -175,7 +175,7 @@ public class Dependency {
mProviders.put(MetricsLogger.class, mMetricsLogger::get);
mProviders.put(UiOffloadThread.class, mUiOffloadThread::get);
mProviders.put(LightBarController.class, mLightBarController::get);
- mProviders.put(OverviewProxyService.class, mOverviewProxyService::get);
+ mProviders.put(LauncherProxyService.class, mLauncherProxyService::get);
mProviders.put(NavigationModeController.class, mNavBarModeController::get);
mProviders.put(NavigationBarController.class, mNavigationBarController::get);
mProviders.put(StatusBarStateController.class, mStatusBarStateController::get);
diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
index 11ce168b9bcb..dbdf93d81eee 100644
--- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
@@ -109,52 +109,75 @@ class FaceScanningOverlay(
requestLayout()
}
- cameraProtectionAnimator?.cancel()
- cameraProtectionAnimator = ValueAnimator.ofFloat(cameraProtectionProgress,
- if (showScanningAnimationNow) SHOW_CAMERA_PROTECTION_SCALE
- else HIDDEN_CAMERA_PROTECTION_SCALE).apply {
- startDelay =
- if (showScanningAnim) 0
- else if (faceAuthSucceeded) PULSE_SUCCESS_DISAPPEAR_DURATION
- else PULSE_ERROR_DISAPPEAR_DURATION
- duration =
- if (showScanningAnim) CAMERA_PROTECTION_APPEAR_DURATION
- else if (faceAuthSucceeded) CAMERA_PROTECTION_SUCCESS_DISAPPEAR_DURATION
- else CAMERA_PROTECTION_ERROR_DISAPPEAR_DURATION
- interpolator =
- if (showScanningAnim) Interpolators.STANDARD_ACCELERATE
- else if (faceAuthSucceeded) Interpolators.STANDARD
- else Interpolators.STANDARD_DECELERATE
- addUpdateListener(this@FaceScanningOverlay::updateCameraProtectionProgress)
+ if (!Flags.faceScanningAnimationNpeFix()) {
+ cameraProtectionAnimator?.cancel()
+ cameraProtectionAnimator = cameraProtectionAnimator(faceAuthSucceeded)
+ }
+
+ rimAnimator?.cancel()
+ rimAnimator = faceScanningRimAnimator(
+ faceAuthSucceeded,
+ if (Flags.faceScanningAnimationNpeFix()) {
+ cameraProtectionAnimator(faceAuthSucceeded)
+ } else {
+ cameraProtectionAnimator
+ },
+ )
+ rimAnimator?.start()
+ }
+
+ private fun faceScanningRimAnimator(
+ faceAuthSucceeded: Boolean,
+ cameraProtectAnimator: ValueAnimator?
+ ): AnimatorSet {
+ return if (showScanningAnim) {
+ createFaceScanningRimAnimator(cameraProtectAnimator)
+ } else if (faceAuthSucceeded) {
+ createFaceSuccessRimAnimator(cameraProtectAnimator)
+ } else {
+ createFaceNotSuccessRimAnimator(cameraProtectAnimator)
+ }.apply {
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- cameraProtectionAnimator = null
+ rimAnimator = null
if (!showScanningAnim) {
- hide()
+ requestLayout()
}
}
})
}
+ }
- rimAnimator?.cancel()
- rimAnimator = if (showScanningAnim) {
- createFaceScanningRimAnimator()
- } else if (faceAuthSucceeded) {
- createFaceSuccessRimAnimator()
- } else {
- createFaceNotSuccessRimAnimator()
- }
- rimAnimator?.apply {
+ private fun cameraProtectionAnimator(faceAuthSucceeded: Boolean): ValueAnimator {
+ return ValueAnimator.ofFloat(
+ cameraProtectionProgress,
+ if (showScanningAnim) SHOW_CAMERA_PROTECTION_SCALE
+ else HIDDEN_CAMERA_PROTECTION_SCALE
+ ).apply {
+ startDelay =
+ if (showScanningAnim) 0
+ else if (faceAuthSucceeded) PULSE_SUCCESS_DISAPPEAR_DURATION
+ else PULSE_ERROR_DISAPPEAR_DURATION
+ duration =
+ if (showScanningAnim) CAMERA_PROTECTION_APPEAR_DURATION
+ else if (faceAuthSucceeded) CAMERA_PROTECTION_SUCCESS_DISAPPEAR_DURATION
+ else CAMERA_PROTECTION_ERROR_DISAPPEAR_DURATION
+ interpolator =
+ if (showScanningAnim) Interpolators.STANDARD_ACCELERATE
+ else if (faceAuthSucceeded) Interpolators.STANDARD
+ else Interpolators.STANDARD_DECELERATE
+ addUpdateListener(this@FaceScanningOverlay::updateCameraProtectionProgress)
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- rimAnimator = null
+ if (!Flags.faceScanningAnimationNpeFix()) {
+ cameraProtectionAnimator = null
+ }
if (!showScanningAnim) {
- requestLayout()
+ hide()
}
}
})
}
- rimAnimator?.start()
}
override fun updateVisOnUpdateCutout(): Boolean {
@@ -219,7 +242,7 @@ class FaceScanningOverlay(
canvas.drawPath(scaledProtectionPath, paint)
}
- private fun createFaceSuccessRimAnimator(): AnimatorSet {
+ private fun createFaceSuccessRimAnimator(cameraProtectAnimator: ValueAnimator?): AnimatorSet {
val rimSuccessAnimator = AnimatorSet()
rimSuccessAnimator.playTogether(
createRimDisappearAnimator(
@@ -230,11 +253,11 @@ class FaceScanningOverlay(
createSuccessOpacityAnimator(),
)
return AnimatorSet().apply {
- playTogether(rimSuccessAnimator, cameraProtectionAnimator)
+ playTogether(rimSuccessAnimator, cameraProtectAnimator)
}
}
- private fun createFaceNotSuccessRimAnimator(): AnimatorSet {
+ private fun createFaceNotSuccessRimAnimator(cameraProtectAnimator: ValueAnimator?): AnimatorSet {
return AnimatorSet().apply {
playTogether(
createRimDisappearAnimator(
@@ -242,7 +265,7 @@ class FaceScanningOverlay(
PULSE_ERROR_DISAPPEAR_DURATION,
Interpolators.STANDARD
),
- cameraProtectionAnimator,
+ cameraProtectAnimator,
)
}
}
@@ -279,11 +302,11 @@ class FaceScanningOverlay(
}
}
- private fun createFaceScanningRimAnimator(): AnimatorSet {
+ private fun createFaceScanningRimAnimator(cameraProtectAnimator: ValueAnimator?): AnimatorSet {
return AnimatorSet().apply {
playSequentially(
- cameraProtectionAnimator,
- createRimAppearAnimator(),
+ cameraProtectAnimator,
+ createRimAppearAnimator(),
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 13cd2c538f3f..19b29206440d 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -19,6 +19,7 @@ package com.android.systemui;
import static androidx.dynamicanimation.animation.DynamicAnimation.TRANSLATION_X;
import static androidx.dynamicanimation.animation.FloatPropertyCompat.createFloatPropertyCompat;
+import static com.android.systemui.Flags.magneticNotificationSwipes;
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS;
import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
@@ -76,8 +77,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
protected final Handler mHandler;
- private final SpringConfig mSnapBackSpringConfig =
- new SpringConfig(SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+ private final SpringConfig mSnapBackSpringConfig;
private final FlingAnimationUtils mFlingAnimationUtils;
private float mPagingTouchSlop;
@@ -153,6 +153,12 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
R.bool.config_fadeDependingOnAmountSwiped);
mFalsingManager = falsingManager;
mFeatureFlags = featureFlags;
+ if (magneticNotificationSwipes()) {
+ mSnapBackSpringConfig = new SpringConfig(550f /*stiffness*/, 0.52f /*dampingRatio*/);
+ } else {
+ mSnapBackSpringConfig = new SpringConfig(
+ SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+ }
mFlingAnimationUtils = new FlingAnimationUtils(resources.getDisplayMetrics(),
getMaxEscapeAnimDuration() / 1000f);
}
@@ -718,7 +724,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
dismissChild(mTouchedView, velocity,
!swipedFastEnough() /* useAccelerateInterpolator */);
} else {
- mCallback.onDragCancelled(mTouchedView);
+ mCallback.onDragCancelledWithVelocity(mTouchedView, velocity);
snapChild(mTouchedView, 0 /* leftTarget */, velocity);
}
mTouchedView = null;
@@ -925,6 +931,15 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
void onDragCancelled(View v);
/**
+ * A drag operation has been cancelled on a view with a final velocity.
+ * @param v View that was dragged.
+ * @param finalVelocity Final velocity of the drag.
+ */
+ default void onDragCancelledWithVelocity(View v, float finalVelocity) {
+ onDragCancelled(v);
+ }
+
+ /**
* Called when the child is long pressed and available to start drag and drop.
*
* @param v the view that was long pressed.
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java
index 5cba464fc24c..5482c3d3ea18 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java
@@ -50,7 +50,7 @@ import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.util.settings.SecureSettings;
@@ -79,7 +79,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks
private final Executor mExecutor;
private final AccessibilityManager mAccessibilityManager;
private final CommandQueue mCommandQueue;
- private final OverviewProxyService mOverviewProxyService;
+ private final LauncherProxyService mLauncherProxyService;
private final DisplayTracker mDisplayTracker;
private final AccessibilityLogger mA11yLogger;
@@ -225,13 +225,13 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks
public MagnificationImpl(Context context,
@Main Handler mainHandler, @Main Executor executor,
CommandQueue commandQueue, ModeSwitchesController modeSwitchesController,
- SysUiState sysUiState, OverviewProxyService overviewProxyService,
+ SysUiState sysUiState, LauncherProxyService launcherProxyService,
SecureSettings secureSettings, DisplayTracker displayTracker,
DisplayManager displayManager, AccessibilityLogger a11yLogger,
IWindowManager iWindowManager, AccessibilityManager accessibilityManager,
ViewCaptureAwareWindowManager viewCaptureAwareWindowManager) {
this(context, mainHandler.getLooper(), executor, commandQueue,
- modeSwitchesController, sysUiState, overviewProxyService, secureSettings,
+ modeSwitchesController, sysUiState, launcherProxyService, secureSettings,
displayTracker, displayManager, a11yLogger, iWindowManager, accessibilityManager,
viewCaptureAwareWindowManager);
}
@@ -239,7 +239,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks
@VisibleForTesting
public MagnificationImpl(Context context, Looper looper, @Main Executor executor,
CommandQueue commandQueue, ModeSwitchesController modeSwitchesController,
- SysUiState sysUiState, OverviewProxyService overviewProxyService,
+ SysUiState sysUiState, LauncherProxyService launcherProxyService,
SecureSettings secureSettings, DisplayTracker displayTracker,
DisplayManager displayManager, AccessibilityLogger a11yLogger,
IWindowManager iWindowManager,
@@ -258,7 +258,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks
mCommandQueue = commandQueue;
mModeSwitchesController = modeSwitchesController;
mSysUiState = sysUiState;
- mOverviewProxyService = overviewProxyService;
+ mLauncherProxyService = launcherProxyService;
mDisplayTracker = displayTracker;
mA11yLogger = a11yLogger;
mWindowMagnificationControllerSupplier = new WindowMagnificationControllerSupplier(context,
@@ -279,7 +279,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks
@Override
public void start() {
mCommandQueue.addCallback(this);
- mOverviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() {
+ mLauncherProxyService.addCallback(new LauncherProxyService.LauncherProxyListener() {
@Override
public void onConnectionChanged(boolean isConnected) {
if (isConnected) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
index 39fd44a83c58..2669348143fe 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
@@ -27,7 +27,6 @@ import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -49,7 +48,6 @@ interface CaptioningRepository {
suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean)
}
-@OptIn(ExperimentalCoroutinesApi::class)
class CaptioningRepositoryImpl
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 939d96e67f8f..da1c1bc49d23 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -37,7 +37,7 @@ import com.android.systemui.assist.ui.DefaultUiController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.res.R;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
@@ -142,7 +142,7 @@ public class AssistManager {
protected final Context mContext;
private final AssistDisclosure mAssistDisclosure;
private final PhoneStateMonitor mPhoneStateMonitor;
- private final OverviewProxyService mOverviewProxyService;
+ private final LauncherProxyService mLauncherProxyService;
private final UiController mUiController;
protected final Lazy<SysUiState> mSysUiState;
protected final AssistLogger mAssistLogger;
@@ -176,7 +176,7 @@ public class AssistManager {
private final CommandQueue mCommandQueue;
protected final AssistUtils mAssistUtils;
- // Invocation types that should be sent over OverviewProxy instead of handled here.
+ // Invocation types that should be sent over LauncherProxy instead of handled here.
private int[] mAssistOverrideInvocationTypes;
@Inject
@@ -186,7 +186,7 @@ public class AssistManager {
AssistUtils assistUtils,
CommandQueue commandQueue,
PhoneStateMonitor phoneStateMonitor,
- OverviewProxyService overviewProxyService,
+ LauncherProxyService launcherProxyService,
Lazy<SysUiState> sysUiState,
DefaultUiController defaultUiController,
AssistLogger assistLogger,
@@ -203,7 +203,7 @@ public class AssistManager {
mCommandQueue = commandQueue;
mAssistUtils = assistUtils;
mAssistDisclosure = new AssistDisclosure(context, uiHandler, viewCaptureAwareWindowManager);
- mOverviewProxyService = overviewProxyService;
+ mLauncherProxyService = launcherProxyService;
mPhoneStateMonitor = phoneStateMonitor;
mAssistLogger = assistLogger;
mUserTracker = userTracker;
@@ -220,7 +220,7 @@ public class AssistManager {
mSysUiState = sysUiState;
- mOverviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() {
+ mLauncherProxyService.addCallback(new LauncherProxyService.LauncherProxyListener() {
@Override
public void onAssistantProgress(float progress) {
// Progress goes from 0 to 1 to indicate how close the assist gesture is to
@@ -288,14 +288,14 @@ public class AssistManager {
}
if (shouldOverrideAssist(args)) {
try {
- if (mOverviewProxyService.getProxy() == null) {
- Log.w(TAG, "No OverviewProxyService to invoke assistant override");
+ if (mLauncherProxyService.getProxy() == null) {
+ Log.w(TAG, "No LauncherProxyService to invoke assistant override");
return;
}
- mOverviewProxyService.getProxy().onAssistantOverrideInvoked(
+ mLauncherProxyService.getProxy().onAssistantOverrideInvoked(
args.getInt(INVOCATION_TYPE_KEY));
} catch (RemoteException e) {
- Log.w(TAG, "Unable to invoke assistant via OverviewProxyService override", e);
+ Log.w(TAG, "Unable to invoke assistant via LauncherProxyService override", e);
}
return;
}
@@ -333,7 +333,7 @@ public class AssistManager {
return shouldOverrideAssist(invocationType);
}
- /** @return true if the invocation type should be handled by OverviewProxy instead of SysUI. */
+ /** @return true if the invocation type should be handled by LauncherProxy instead of SysUI. */
public boolean shouldOverrideAssist(int invocationType) {
return mAssistOverrideInvocationTypes != null
&& Arrays.stream(mAssistOverrideInvocationTypes).anyMatch(
@@ -342,7 +342,7 @@ public class AssistManager {
/**
* @param invocationTypes The invocation types that will henceforth be handled via
- * OverviewProxy (Launcher); other invocation types should be handled by
+ * LauncherProxy (Launcher); other invocation types should be handled by
* this class.
*/
public void setAssistantOverridesRequested(int[] invocationTypes) {
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index a061d38d0c18..27250df65c66 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.authentication.data.repository
import android.annotation.UserIdInt
@@ -48,7 +46,6 @@ import java.util.function.Function
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index a9133e45e93f..fd11fa5d3e80 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -61,7 +61,6 @@ import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.OptIn;
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.internal.R;
@@ -113,7 +112,6 @@ import dagger.Lazy;
import kotlin.Unit;
import kotlinx.coroutines.CoroutineScope;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -264,7 +262,6 @@ public class UdfpsController implements DozeReceiver, Dumpable {
}
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
- @OptIn(markerClass = ExperimentalCoroutinesApi.class)
@Override
public void showUdfpsOverlay(long requestId, int sensorId, int reason,
@NonNull IUdfpsOverlayControllerCallback callback) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 671ca8bfe513..702f23718ee8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -69,7 +69,6 @@ import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import dagger.Lazy
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
@@ -83,7 +82,6 @@ private const val TAG = "UdfpsControllerOverlay"
* Keeps track of the overlay state and UI resources associated with a single FingerprintService
* request. This state can persist across configuration changes via the [show] and [hide] methods.
*/
-@ExperimentalCoroutinesApi
@UiThread
class UdfpsControllerOverlay
@JvmOverloads
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.kt
index afe37d496150..abdcbc021fed 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.kt
@@ -18,10 +18,8 @@ package com.android.systemui.biometrics
import android.content.Context
import android.util.AttributeSet
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** View corresponding with udfps_keyguard_view.xml */
-@ExperimentalCoroutinesApi
class UdfpsKeyguardView(
context: Context,
attrs: AttributeSet?,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractor.kt
index 6c9be81ccaac..0755daf7574c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractor.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.biometrics.domain.interactor
import android.hardware.biometrics.AuthenticateOptions
@@ -32,7 +30,6 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.Flow
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
index 52e85576e756..a1744244ba10 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
@@ -34,7 +34,6 @@ import com.android.systemui.log.SideFpsLogger
import com.android.systemui.res.R
import java.util.Optional
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -44,7 +43,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
-@ExperimentalCoroutinesApi
@SysUISingleton
class SideFpsSensorInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
index 8fe5ded939e2..6cd763a9d3d0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
@@ -49,12 +49,10 @@ import com.android.systemui.util.kotlin.sample
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.combine
import com.android.app.tracing.coroutines.launchTraced as launch
/** Binds the side fingerprint sensor indicator view to [SideFpsOverlayViewModel]. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class SideFpsOverlayViewBinder
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/UdfpsTouchOverlayBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/UdfpsTouchOverlayBinder.kt
index 8763e5ccabe9..68a4faf13a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/UdfpsTouchOverlayBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/UdfpsTouchOverlayBinder.kt
@@ -24,10 +24,8 @@ import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay
import com.android.systemui.biometrics.ui.viewmodel.UdfpsTouchOverlayViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import com.android.app.tracing.coroutines.launchTraced as launch
-@ExperimentalCoroutinesApi
object UdfpsTouchOverlayBinder {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModel.kt
index f8338aea4150..905b183be56c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModel.kt
@@ -20,7 +20,6 @@ import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.hideAffordancesRequest
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -31,7 +30,6 @@ import kotlinx.coroutines.flow.combine
* - shade is fully or partially expanded
* - any SysUI dialogs are obscuring the display
*/
-@ExperimentalCoroutinesApi
class DefaultUdfpsTouchOverlayViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt
index 07e30ce242bd..47277e1b043a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModel.kt
@@ -22,7 +22,6 @@ import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.hideAffordancesRequest
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -33,7 +32,6 @@ import kotlinx.coroutines.flow.map
* touches as long as the device entry view is visible (the lockscreen or the alternate bouncer
* view).
*/
-@ExperimentalCoroutinesApi
class DeviceEntryUdfpsTouchOverlayViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
index 555716191c96..19930efe468d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
@@ -39,14 +39,12 @@ import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlay
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
/** Models UI of the side fingerprint sensor indicator view. */
-@OptIn(ExperimentalCoroutinesApi::class)
class SideFpsOverlayViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt
index 116e76c82008..832afb1799b1 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt
@@ -22,21 +22,25 @@ import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
import com.android.settingslib.bluetooth.onBroadcastMetadataChanged
+import com.android.settingslib.bluetooth.onBroadcastStartedOrStopped
import com.android.settingslib.flags.Flags.audioSharingQsDialogImprovement
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.withContext
/** Holds business logic for the audio sharing state. */
@@ -63,7 +67,6 @@ interface AudioSharingInteractor {
}
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
open class AudioSharingInteractorImpl
@Inject
constructor(
@@ -73,6 +76,7 @@ constructor(
@Background private val backgroundDispatcher: CoroutineDispatcher,
) : AudioSharingInteractor {
+ private val audioSharingStartedEvents = Channel<Unit>(Channel.BUFFERED)
private var previewEnabled: Boolean? = null
override val isAudioSharingOn: Flow<Boolean> =
@@ -101,12 +105,18 @@ constructor(
withContext(backgroundDispatcher) {
if (audioSharingAvailable()) {
audioSharingRepository.leAudioBroadcastProfile?.let { profile ->
- isAudioSharingOn
- // Skip the default value, we only care about adding source for newly
- // started audio sharing session
- .drop(1)
- .mapNotNull { audioSharingOn ->
- if (audioSharingOn) {
+ merge(
+ // Register and start listen to onBroadcastMetadataChanged (means ready
+ // to add source)
+ audioSharingStartedEvents.receiveAsFlow().map { true },
+ // When session is off or failed to start, stop listening to
+ // onBroadcastMetadataChanged as we won't be adding source
+ profile.onBroadcastStartedOrStopped
+ .filterNot { profile.isEnabled(null) }
+ .map { false },
+ )
+ .mapNotNull { shouldListenToMetadata ->
+ if (shouldListenToMetadata) {
// onBroadcastMetadataChanged could emit multiple times during one
// audio sharing session, we only perform add source on the first
// time
@@ -148,6 +158,7 @@ constructor(
if (!audioSharingAvailable()) {
return
}
+ audioSharingStartedEvents.trySend(Unit)
audioSharingRepository.startAudioSharing()
}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt
index d69e41626bd6..9019051185fa 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt
@@ -25,7 +25,6 @@ import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChangedBy
@@ -33,7 +32,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.merge
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class BluetoothDeviceMetadataInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
index 9460e7c2c8d5..bf04897f6d10 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
@@ -87,7 +87,6 @@ constructor(
*
* @param view The view from which the dialog is shown.
*/
- @kotlinx.coroutines.ExperimentalCoroutinesApi
fun showDialog(expandable: Expandable?) {
cancelJob()
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
index e52ddb2d143b..b5a38d8f2991 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
@@ -43,7 +43,6 @@ import com.android.systemui.util.kotlin.combine
import javax.inject.Inject
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
@@ -58,7 +57,6 @@ private const val REBOOT_MAINLINE_UPDATE = "reboot,mainline_update"
private const val TAG = "BouncerMessageInteractor"
/** Handles business logic for the primary bouncer message area. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class BouncerMessageInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt b/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt
index fa57ab967f31..56a95dd0b234 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/log/BouncerLoggerStartable.kt
@@ -26,12 +26,10 @@ import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprint
import com.android.systemui.log.BouncerLogger
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
import com.android.app.tracing.coroutines.launchTraced as launch
/** Startable that logs the flows that bouncer depends on. */
-@OptIn(ExperimentalCoroutinesApi::class)
class BouncerLoggerStartable
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
index 8a4cc63f65fb..116c9415bd11 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
@@ -22,10 +22,8 @@ import dagger.Lazy
import java.util.Optional
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Helper data class that allows to lazy load all the dependencies of the legacy bouncer. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
data class LegacyBouncerDependencies
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
index a6874b00ebfa..fafde96dd454 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
@@ -48,7 +48,6 @@ import dagger.assisted.AssistedInject
import kotlin.math.ceil
import kotlin.math.max
import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.coroutineScope
@@ -64,7 +63,6 @@ import kotlinx.coroutines.flow.map
import com.android.app.tracing.coroutines.launchTraced as launch
/** Holds UI state for the 2-line status message shown on the bouncer. */
-@OptIn(ExperimentalCoroutinesApi::class)
class BouncerMessageViewModel
@AssistedInject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
index 3fef766ab250..24e85fb43e70 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -22,12 +22,10 @@ import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.bouncer.ui.BouncerViewDelegate
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
/** Models UI state for the lock screen bouncer; handles user input. */
-@ExperimentalCoroutinesApi
class KeyguardBouncerViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
index 73aaf7f8e460..c9ae20d25f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.bouncer.ui.viewmodel
import android.content.Context
@@ -39,7 +37,6 @@ import com.android.systemui.res.R
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
diff --git a/packages/SystemUI/src/com/android/systemui/brightness/data/repository/BrightnessPolicyRepository.kt b/packages/SystemUI/src/com/android/systemui/brightness/data/repository/BrightnessPolicyRepository.kt
index 0544a4f66295..6e1cd2d2a4d5 100644
--- a/packages/SystemUI/src/com/android/systemui/brightness/data/repository/BrightnessPolicyRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/brightness/data/repository/BrightnessPolicyRepository.kt
@@ -28,7 +28,6 @@ import com.android.systemui.utils.PolicyRestriction
import com.android.systemui.utils.UserRestrictionChecker
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapLatest
@@ -48,7 +47,6 @@ interface BrightnessPolicyRepository {
}
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class BrightnessPolicyRepositoryImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/common/domain/interactor/PackageChangeInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/domain/interactor/PackageChangeInteractor.kt
index 59c19235ab02..0d6f568c658f 100644
--- a/packages/SystemUI/src/com/android/systemui/common/domain/interactor/PackageChangeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/domain/interactor/PackageChangeInteractor.kt
@@ -22,7 +22,6 @@ import com.android.systemui.common.shared.model.PackageChangeModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
@@ -31,7 +30,6 @@ import kotlinx.coroutines.flow.flatMapLatest
* Allows listening to package updates. This is recommended over registering broadcasts directly as
* it avoids the delay imposed by broadcasts, and provides more structured updates.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class PackageChangeInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt b/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt
index 5671fa49c716..445262761dec 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt
@@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.common.ui.data.repository
import android.content.Context
@@ -36,7 +34,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
index 4d39b033cd7b..8c123d31327c 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
@@ -13,15 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.common.ui.domain.interactor
import android.content.res.Configuration
import android.graphics.Rect
import android.view.Surface
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
index 34679b08cf20..fc589b220f2f 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
@@ -54,7 +54,6 @@ import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
@@ -69,7 +68,6 @@ import kotlinx.coroutines.withContext
* A [CoreStartable] responsible for automatically navigating between communal scenes when certain
* conditions are met.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalSceneStartable
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java b/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
new file mode 100644
index 000000000000..2e1b5ad177b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/DeviceInactiveCondition.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.communal;
+
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.dagger.qualifiers.Application;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import kotlinx.coroutines.CoroutineScope;
+
+import javax.inject.Inject;
+
+/**
+ * Condition which estimates device inactivity in order to avoid launching a full-screen activity
+ * while the user is actively using the device.
+ */
+public class DeviceInactiveCondition extends Condition {
+ private final KeyguardStateController mKeyguardStateController;
+ private final WakefulnessLifecycle mWakefulnessLifecycle;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final KeyguardStateController.Callback mKeyguardStateCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onKeyguardShowingChanged() {
+ updateState();
+ }
+ };
+ private final WakefulnessLifecycle.Observer mWakefulnessObserver =
+ new WakefulnessLifecycle.Observer() {
+ @Override
+ public void onStartedGoingToSleep() {
+ updateState();
+ }
+ };
+ private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onDreamingStateChanged(boolean dreaming) {
+ updateState();
+ }
+ };
+
+ @Inject
+ public DeviceInactiveCondition(@Application CoroutineScope scope,
+ KeyguardStateController keyguardStateController,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ super(scope);
+ mKeyguardStateController = keyguardStateController;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ }
+
+ @Override
+ protected void start() {
+ updateState();
+ mKeyguardStateController.addCallback(mKeyguardStateCallback);
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
+ mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
+ }
+
+ @Override
+ protected void stop() {
+ mKeyguardStateController.removeCallback(mKeyguardStateCallback);
+ mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
+ mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
+ }
+
+ @Override
+ protected int getStartStrategy() {
+ return START_EAGERLY;
+ }
+
+ private void updateState() {
+ final boolean asleep =
+ mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
+ || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP;
+ updateCondition(asleep || mKeyguardStateController.isShowing()
+ || mKeyguardUpdateMonitor.isDreaming());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt
index a02bc8b89910..090264678f35 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt
@@ -32,7 +32,6 @@ import com.android.systemui.util.kotlin.SharedPreferencesExt.observe
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
@@ -59,7 +58,6 @@ interface CommunalPrefsRepository {
suspend fun setHubOnboardingDismissed(user: UserInfo)
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalPrefsRepositoryImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt
index 415fd4e2fe6a..643d185f1939 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt
@@ -27,7 +27,6 @@ import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.scene.shared.model.SceneDataSource
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -61,7 +60,6 @@ interface CommunalSceneRepository {
fun setTransitionState(transitionState: Flow<ObservableTransitionState>?)
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalSceneRepositoryImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
index 73c0179cf8ec..53122c56ed2c 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
@@ -32,6 +32,7 @@ import com.android.systemui.communal.data.model.DisabledReason.DISABLED_REASON_D
import com.android.systemui.communal.data.model.DisabledReason.DISABLED_REASON_FLAG
import com.android.systemui.communal.data.model.DisabledReason.DISABLED_REASON_INVALID_USER
import com.android.systemui.communal.data.model.DisabledReason.DISABLED_REASON_USER_SETTING
+import com.android.systemui.communal.data.repository.CommunalSettingsRepositoryModule.Companion.DEFAULT_BACKGROUND_TYPE
import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -43,6 +44,7 @@ import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import java.util.EnumSet
import javax.inject.Inject
+import javax.inject.Named
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -99,6 +101,7 @@ constructor(
private val secureSettings: SecureSettings,
private val broadcastDispatcher: BroadcastDispatcher,
private val devicePolicyManager: DevicePolicyManager,
+ @Named(DEFAULT_BACKGROUND_TYPE) private val defaultBackgroundType: CommunalBackgroundType,
) : CommunalSettingsRepository {
override fun getFlagEnabled(): Boolean {
@@ -175,11 +178,11 @@ constructor(
val intType =
secureSettings.getIntForUser(
GLANCEABLE_HUB_BACKGROUND_SETTING,
- CommunalBackgroundType.ANIMATED.value,
+ defaultBackgroundType.value,
user.id,
)
CommunalBackgroundType.entries.find { type -> type.value == intType }
- ?: CommunalBackgroundType.ANIMATED
+ ?: defaultBackgroundType
}
private fun getEnabledByUser(user: UserInfo): Flow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt
index a931d3f7ec5b..0f25225b9489 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryModule.kt
@@ -16,11 +16,29 @@
package com.android.systemui.communal.data.repository
+import com.android.systemui.Flags.glanceableHubBlurredBackground
+import com.android.systemui.communal.shared.model.CommunalBackgroundType
import dagger.Binds
import dagger.Module
+import dagger.Provides
+import javax.inject.Named
@Module
interface CommunalSettingsRepositoryModule {
+ companion object {
+ const val DEFAULT_BACKGROUND_TYPE = "default_background_type"
+
+ @Provides
+ @Named(DEFAULT_BACKGROUND_TYPE)
+ fun providesDefaultBackgroundType(): CommunalBackgroundType {
+ if (glanceableHubBlurredBackground()) {
+ return CommunalBackgroundType.BLUR
+ }
+
+ return CommunalBackgroundType.ANIMATED
+ }
+ }
+
@Binds
fun communalSettingsRepository(impl: CommunalSettingsRepositoryImpl): CommunalSettingsRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalTutorialRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalTutorialRepository.kt
index 4c06e97c89b0..19666e4df1cf 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalTutorialRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalTutorialRepository.kt
@@ -34,7 +34,6 @@ import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -59,7 +58,6 @@ interface CommunalTutorialRepository {
suspend fun setTutorialState(@HubModeTutorialState state: Int)
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalTutorialRepositoryImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
index e44d78baeb35..873399fd8fce 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
@@ -47,7 +47,6 @@ import javax.inject.Inject
import kotlin.coroutines.cancellation.CancellationException
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
@@ -168,7 +167,6 @@ constructor(
}
}
- @OptIn(ExperimentalCoroutinesApi::class)
override val communalWidgets: Flow<List<CommunalWidgetContentModel>> =
widgetEntries
.flatMapLatest { widgetEntries ->
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 947113da0e60..74c335e79d4e 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -28,12 +28,14 @@ import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
import com.android.systemui.Flags.communalResponsiveGrid
+import com.android.systemui.Flags.glanceableHubBlurredBackground
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.communal.data.repository.CommunalMediaRepository
import com.android.systemui.communal.data.repository.CommunalSmartspaceRepository
import com.android.systemui.communal.data.repository.CommunalWidgetRepository
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.domain.model.CommunalContentModel.WidgetContent
+import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.communal.shared.model.CommunalContentSize
import com.android.systemui.communal.shared.model.CommunalContentSize.FixedSize.FULL
import com.android.systemui.communal.shared.model.CommunalContentSize.FixedSize.HALF
@@ -69,7 +71,6 @@ import javax.inject.Inject
import kotlin.time.Duration.Companion.minutes
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
@@ -92,7 +93,6 @@ import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
/** Encapsulates business-logic related to communal mode. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalInteractor
@Inject
@@ -311,6 +311,25 @@ constructor(
)
/**
+ * Flow that emits {@code true} whenever communal is influencing the shown background on the
+ * screen. This happens when the background for communal is set to blur and communal is visible.
+ * This is used by other components to determine when blur-related emitted values for communal
+ * should be considered.
+ */
+ val isCommunalBlurring: StateFlow<Boolean> =
+ communalSceneInteractor.isCommunalVisible
+ .combine(communalSettingsInteractor.communalBackground) { showing, background ->
+ showing &&
+ background == CommunalBackgroundType.BLUR &&
+ glanceableHubBlurredBackground()
+ }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = false,
+ )
+
+ /**
* Flow that emits a boolean if the communal UI is fully visible and not in transition.
*
* This will not be true while transitioning to the hub and will turn false immediately when a
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt
index 76e6cde4ad81..ec45d6c8d545 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt
@@ -27,14 +27,12 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalPrefsInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
index ae08f2b8c45e..476493225857 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
@@ -36,7 +36,6 @@ import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
import com.android.systemui.util.kotlin.pairwiseBy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -51,7 +50,6 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalSceneInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
index c1f21e4046a3..1738f37b7f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
@@ -32,7 +32,6 @@ import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalSettingsInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt
index 6fa066306287..4e4ecc949d09 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt
@@ -26,7 +26,6 @@ import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -42,7 +41,6 @@ import kotlinx.coroutines.flow.transformWhile
import com.android.app.tracing.coroutines.launchTraced as launch
/** Encapsulates business-logic related to communal tutorial state. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalTutorialInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt
index f49394ad37bb..02d02665d353 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt
@@ -38,7 +38,6 @@ import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.takeWhile
@@ -51,7 +50,6 @@ import kotlinx.coroutines.withTimeout
* widget interaction occurring. Used for detecting non-activity trampolines which otherwise would
* not prompt the user for authentication.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class WidgetTrampolineInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt
index 3b23ba955899..e1128ed3a801 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalBackgroundType.kt
@@ -22,4 +22,5 @@ enum class CommunalBackgroundType(val value: Int) {
STATIC_GRADIENT(1),
ANIMATED(2),
NONE(3),
+ BLUR(4),
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
index 34962305ff2a..0cbbfd4e2cd7 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
@@ -37,7 +37,6 @@ import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
@@ -49,7 +48,6 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
/** View model for transitions related to the communal hub. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index 16cf26393aee..4bc44005d2fc 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -53,7 +53,6 @@ import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
@@ -73,7 +72,6 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
/** The default view model used for showing the communal hub. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalViewModel
@Inject
@@ -136,7 +134,6 @@ constructor(
}
}
- @OptIn(ExperimentalCoroutinesApi::class)
private val latestCommunalContent: Flow<List<CommunalContentModel>> =
tutorialInteractor.isTutorialAvailable
.flatMapLatest { isTutorialMode ->
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt
index 691ec76d50ed..f7a2c6e0329d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt
@@ -33,7 +33,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
-@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
@SysUISingleton
class SelectedComponentRepositoryImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt
index 436b8cb851ab..6f579a3986c8 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsRepositoryImpl.kt
@@ -28,7 +28,6 @@ import com.android.systemui.util.settings.SecureSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -57,7 +56,6 @@ constructor(
override val allowActionOnTrivialControlsInLockscreen =
makeFlowForSetting(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS)
- @OptIn(ExperimentalCoroutinesApi::class)
private fun makeFlowForSetting(setting: String): StateFlow<Boolean> {
return userRepository.selectedUserInfo
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index c02784dfab1b..fe5a82cb5b8c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -81,6 +81,7 @@ import com.android.systemui.keyguard.ui.composable.LockscreenContent;
import com.android.systemui.log.dagger.LogModule;
import com.android.systemui.log.dagger.MonitorLog;
import com.android.systemui.log.table.TableLogBuffer;
+import com.android.systemui.lowlightclock.dagger.LowLightModule;
import com.android.systemui.mediaprojection.MediaProjectionModule;
import com.android.systemui.mediaprojection.appselector.MediaProjectionActivitiesModule;
import com.android.systemui.mediaprojection.taskswitcher.MediaProjectionTaskSwitcherModule;
@@ -285,7 +286,8 @@ import javax.inject.Named;
UserModule.class,
UtilModule.class,
NoteTaskModule.class,
- WalletModule.class
+ WalletModule.class,
+ LowLightModule.class
},
subcomponents = {
ComplicationComponent.class,
diff --git a/packages/SystemUI/src/com/android/systemui/development/domain/interactor/BuildNumberInteractor.kt b/packages/SystemUI/src/com/android/systemui/development/domain/interactor/BuildNumberInteractor.kt
index 4d786fe76bc1..fa5556d44674 100644
--- a/packages/SystemUI/src/com/android/systemui/development/domain/interactor/BuildNumberInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/development/domain/interactor/BuildNumberInteractor.kt
@@ -32,13 +32,11 @@ import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.user.utils.UserScopedService
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class BuildNumberInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractor.kt
index 337fe1ea7d98..54f3d7963e61 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/AuthRippleInteractor.kt
@@ -18,7 +18,6 @@ package com.android.systemui.deviceentry.domain.interactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
@@ -26,7 +25,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
/** Business logic for device entry auth ripple interactions. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class AuthRippleInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractor.kt
index 9919f09935c3..4edc5db5d6e0 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractor.kt
@@ -36,7 +36,6 @@ import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthentication
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
@@ -51,7 +50,6 @@ import kotlinx.coroutines.flow.merge
* BiometricMessage business logic. Filters biometric error/fail/success events for authentication
* events that should never surface a message to the user at the current device state.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class BiometricMessageInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
index 569917630e50..1e7bec257432 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
@@ -21,7 +21,6 @@ import com.android.systemui.deviceentry.shared.DeviceEntryBiometricMode
import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow
@@ -30,7 +29,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
/** Business logic for device entry biometric states that may differ based on the biometric mode. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryBiometricAuthInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricSettingsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricSettingsInteractor.kt
index d495facdfe9d..bd80dc09109c 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricSettingsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricSettingsInteractor.kt
@@ -20,12 +20,10 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.shared.model.AuthenticationFlags
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
/** Encapsulates business logic for device entry biometric settings. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryBiometricSettingsInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt
index 7aee12f70f41..5b03ccd5d43d 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt
@@ -20,7 +20,6 @@ import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
@@ -35,7 +34,6 @@ import kotlinx.coroutines.flow.map
* This class coordinates the lockout states of each individual biometric based on the lockout
* states of other biometrics.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class DeviceEntryBiometricsAllowedInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
index 5c058fe92ccb..db92e11f9d24 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
@@ -26,13 +26,11 @@ import com.android.systemui.keyguard.shared.model.FingerprintAuthenticationStatu
import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.map
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class DeviceEntryFingerprintAuthInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
index ae6238724042..cd456a618c48 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
@@ -29,7 +29,6 @@ import com.android.systemui.util.kotlin.FlowDumperImpl
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combineTransform
@@ -44,7 +43,6 @@ import kotlinx.coroutines.flow.onStart
* particular, there are extra guards for whether device entry error and successes haptics should
* play when the physical fingerprint sensor is located on the power button.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryHapticsInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index 2e1096fcae36..4ddc98cd434f 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -33,7 +33,6 @@ import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -51,7 +50,6 @@ import kotlinx.coroutines.flow.stateIn
* Device entry occurs when the user successfully dismisses (or bypasses) the lockscreen, regardless
* of the authentication method used.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt
index b2d4405ee6be..eb82c7d4ce6a 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt
@@ -49,7 +49,6 @@ import com.android.systemui.util.kotlin.Utils.Companion.sampleFilter
import com.android.systemui.util.kotlin.combine
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.combine
@@ -68,7 +67,6 @@ import kotlinx.coroutines.flow.merge
* bypass biometric or, if the device is already unlocked, by triggering an affordance that
* dismisses the lockscreen.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntrySourceInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
index 911327a0bd18..8ff894775b17 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
@@ -22,7 +22,6 @@ import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.shared.customization.data.SensorLocation
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
@@ -30,7 +29,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
/** Encapsulates business logic for device entry under-display fingerprint state changes. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryUdfpsInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt
index 5e3b2ae0b59f..68aef521be7b 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt
@@ -41,7 +41,6 @@ import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
@@ -61,7 +60,6 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class DeviceUnlockedInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
index e81164b94d7c..7623e53c87a4 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
@@ -25,7 +25,6 @@ import com.android.systemui.deviceentry.shared.model.AcquiredFaceAuthenticationS
import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filterIsInstance
@@ -37,7 +36,6 @@ import com.android.app.tracing.coroutines.launchTraced as launch
* events to determine whether a face auth event should be displayed to the user immediately or when
* a [FaceManager.FACE_ERROR_TIMEOUT] is received.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class FaceHelpMessageDeferralInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractor.kt
index 15631f8d7abd..e416b924914f 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/OccludingAppDeviceEntryInteractor.kt
@@ -40,7 +40,6 @@ import com.android.systemui.util.kotlin.combine
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -52,7 +51,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
/** Business logic for handling authentication events when an app is occluding the lockscreen. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class OccludingAppDeviceEntryInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt
index ef2537c1bebb..e2172d0773d3 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt
@@ -24,9 +24,7 @@ import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.deviceentry.ui.view.UdfpsAccessibilityOverlay
import com.android.systemui.deviceentry.ui.viewmodel.UdfpsAccessibilityOverlayViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-@ExperimentalCoroutinesApi
object UdfpsAccessibilityOverlayBinder {
/** Forwards hover events to the view model to make guided announcements for accessibility. */
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt
index eeac52783bcf..5c7cd5f55942 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt
@@ -19,12 +19,10 @@ package com.android.systemui.deviceentry.ui.viewmodel
import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
/** Models the UI state for the alternate bouncer UDFPS accessibility overlay */
-@ExperimentalCoroutinesApi
class AlternateBouncerUdfpsAccessibilityOverlayViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt
index af51576817e5..b84d65a2b430 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt
@@ -22,12 +22,10 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
/** Models the UI state for the non-alternate bouncer UDFPS accessibility overlay */
-@ExperimentalCoroutinesApi
class DeviceEntryUdfpsAccessibilityOverlayViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt
index 191d612d3668..fa849bf5e413 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt
@@ -23,14 +23,12 @@ import com.android.systemui.accessibility.domain.interactor.AccessibilityInterac
import com.android.systemui.biometrics.UdfpsUtils
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
/** Models the UI state for the UDFPS accessibility overlay */
-@ExperimentalCoroutinesApi
abstract class UdfpsAccessibilityOverlayViewModel(
udfpsOverlayInteractor: UdfpsOverlayInteractor,
accessibilityInteractor: AccessibilityInteractor,
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 faab31eff4f7..15f73ee0eda6 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -48,6 +48,8 @@ import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig;
import com.android.systemui.res.R;
import com.android.systemui.touch.TouchInsetManager;
+import com.google.android.systemui.lowlightclock.LowLightClockDreamService;
+
import dagger.Binds;
import dagger.BindsOptionalOf;
import dagger.Module;
@@ -238,15 +240,24 @@ public interface DreamModule {
ComponentName bindsLowLightClockDream();
/**
+ * Provides low light clock dream service component.
+ */
+ @Provides
+ @Named(LOW_LIGHT_CLOCK_DREAM)
+ static ComponentName providesLowLightClockDream(Context context) {
+ return new ComponentName(context, LowLightClockDreamService.class);
+ }
+
+ /**
* Provides the component name of the low light dream, or null if not configured.
*/
@Provides
@Nullable
@Named(LOW_LIGHT_DREAM_SERVICE)
static ComponentName providesLowLightDreamService(Context context,
- @Named(LOW_LIGHT_CLOCK_DREAM) Optional<ComponentName> clockDream) {
- if (Flags.lowLightClockDream() && clockDream.isPresent()) {
- return clockDream.get();
+ @Named(LOW_LIGHT_CLOCK_DREAM) ComponentName clockDream) {
+ if (Flags.lowLightClockDream()) {
+ return clockDream;
}
String lowLightDreamComponent = context.getResources().getString(
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/service/RemoteHomeControlsDataSourceDelegator.kt b/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/service/RemoteHomeControlsDataSourceDelegator.kt
index b14903d7885f..7938889d50d1 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/service/RemoteHomeControlsDataSourceDelegator.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/service/RemoteHomeControlsDataSourceDelegator.kt
@@ -30,7 +30,6 @@ import com.android.systemui.util.service.ObservableServiceConnection
import com.android.systemui.util.service.PersistentConnectionManager
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -45,7 +44,6 @@ import kotlinx.coroutines.flow.onEach
* Queries a remote service for [HomeControlsComponentInfo] necessary to show the home controls
* dream.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class RemoteHomeControlsDataSourceDelegator
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/system/domain/interactor/HomeControlsComponentInteractor.kt b/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/system/domain/interactor/HomeControlsComponentInteractor.kt
index 31bd70897f24..26aa0211cbca 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/system/domain/interactor/HomeControlsComponentInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/system/domain/interactor/HomeControlsComponentInteractor.kt
@@ -29,7 +29,6 @@ import com.android.systemui.util.kotlin.getOrNull
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -42,7 +41,6 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
class HomeControlsComponentInteractor
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
index 5c0335a6dfae..02e1824dc7dd 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
@@ -34,14 +34,12 @@ import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.kotlin.FlowDumperImpl
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.merge
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class DreamViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt
index 9596a540b63b..0640351c8149 100644
--- a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt
@@ -113,7 +113,6 @@ constructor(
private val datastore = MutableStateFlow<DataStore<Preferences>?>(null)
- @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
private val prefData: Flow<Preferences> = datastore.filterNotNull().flatMapLatest { it.data }
override val keyboardShortcutTriggered: Flow<GestureType> =
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
index d7a4dba3188a..685150f9b0e6 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
@@ -37,8 +37,8 @@ import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD
import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
-import com.android.systemui.recents.OverviewProxyService
-import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
+import com.android.systemui.recents.LauncherProxyService
+import com.android.systemui.recents.LauncherProxyService.LauncherProxyListener
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import java.time.Clock
import java.time.Instant
@@ -48,7 +48,6 @@ import kotlin.time.Duration.Companion.days
import kotlin.time.DurationUnit
import kotlin.time.toDuration
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -67,7 +66,7 @@ constructor(
private val contextualEducationInteractor: ContextualEducationInteractor,
private val userInputDeviceRepository: UserInputDeviceRepository,
private val tutorialRepository: TutorialSchedulerRepository,
- private val overviewProxyService: OverviewProxyService,
+ private val launcherProxyService: LauncherProxyService,
private val metricsLogger: ContextualEducationMetricsLogger,
@EduClock private val clock: Clock,
) : CoreStartable {
@@ -100,8 +99,8 @@ constructor(
val educationTriggered = _educationTriggered.asStateFlow()
private val statsUpdateRequests: Flow<StatsUpdateRequest> = conflatedCallbackFlow {
- val listener: OverviewProxyListener =
- object : OverviewProxyListener {
+ val listener: LauncherProxyListener =
+ object : LauncherProxyListener {
override fun updateContextualEduStats(
isTrackpadGesture: Boolean,
gestureType: GestureType,
@@ -113,8 +112,8 @@ constructor(
}
}
- overviewProxyService.addCallback(listener)
- awaitClose { overviewProxyService.removeCallback(listener) }
+ launcherProxyService.addCallback(listener)
+ awaitClose { launcherProxyService.removeCallback(listener) }
}
private val gestureModelMap: Flow<Map<GestureType, GestureEduModel>> =
@@ -127,7 +126,6 @@ constructor(
mapOf(BACK to back, HOME to home, OVERVIEW to overview, ALL_APPS to allApps)
}
- @OptIn(ExperimentalCoroutinesApi::class)
override fun start() {
backgroundScope.launch {
contextualEducationInteractor.eduDeviceConnectionTimeFlow
diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt
index 443ad020a570..e1113ec43588 100644
--- a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt
@@ -37,7 +37,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
-@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
@SysUISingleton
class ContextualEduViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index e58807763597..200a751cf825 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -32,7 +32,6 @@ import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyS
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionRefactor
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiAod
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiForceExpanded
import com.android.systemui.statusbar.notification.shared.NotificationAvalancheSuppression
import com.android.systemui.statusbar.notification.shared.NotificationMinimalism
import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun
@@ -55,8 +54,6 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha
NotificationMinimalism.token dependsOn NotificationThrottleHun.token
ModesEmptyShadeFix.token dependsOn modesUi
- PromotedNotificationUiForceExpanded.token dependsOn PromotedNotificationUi.token
-
PromotedNotificationUiAod.token dependsOn PromotedNotificationUi.token
// SceneContainer dependencies
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 2c33c0b4403b..d9d39953e99a 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -206,9 +206,6 @@ object Flags {
// TODO(b/267007629): Tracking Bug
val MEDIA_RESUME_PROGRESS = releasedFlag("media_resume_progress")
- // TODO(b/267166152) : Tracking Bug
- val MEDIA_RETAIN_RECOMMENDATIONS = unreleasedFlag("media_retain_recommendations")
-
// TODO(b/270437894): Tracking Bug
val MEDIA_REMOTE_RESUME = unreleasedFlag("media_remote_resume")
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt b/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt
index 49625f8f9360..70a40d933724 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt
@@ -30,7 +30,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -41,7 +40,6 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.transform
/** A view-model to trigger haptic feedback on Quick Settings tiles */
-@OptIn(ExperimentalCoroutinesApi::class)
class TileHapticsViewModel
@AssistedInject
constructor(
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
index df2a33f95872..edf84b2f3867 100644
--- 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
@@ -21,7 +21,6 @@ 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.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -35,7 +34,6 @@ constructor(
) {
/** Emits current backlight level as [BacklightModel] or null if keyboard is not connected */
- @ExperimentalCoroutinesApi
val backlight: Flow<BacklightModel?> =
keyboardRepository.isAnyKeyboardConnected.flatMapLatest { connected ->
if (connected) keyboardRepository.backlight else flowOf(null)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt
index e5c638cbdfba..d355f761e5ae 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt
@@ -32,18 +32,19 @@ import com.android.systemui.keyboard.shared.model.ShortcutCustomizationRequestRe
import com.android.systemui.keyboard.shared.model.ShortcutCustomizationRequestResult.ERROR_RESERVED_COMBINATION
import com.android.systemui.keyboard.shared.model.ShortcutCustomizationRequestResult.SUCCESS
import com.android.systemui.settings.UserTracker
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext
-import javax.inject.Inject
-import kotlin.coroutines.CoroutineContext
@SysUISingleton
class CustomInputGesturesRepository
@Inject
-constructor(private val userTracker: UserTracker,
- @Background private val bgCoroutineContext: CoroutineContext)
-{
+constructor(
+ private val userTracker: UserTracker,
+ @Background private val bgCoroutineContext: CoroutineContext,
+) {
private val userContext: Context
get() = userTracker.createCurrentUserContext(userTracker.userContext)
@@ -55,8 +56,7 @@ constructor(private val userTracker: UserTracker,
private val _customInputGesture = MutableStateFlow<List<InputGestureData>>(emptyList())
- val customInputGestures =
- _customInputGesture.onStart { refreshCustomInputGestures() }
+ val customInputGestures = _customInputGesture.onStart { refreshCustomInputGestures() }
fun refreshCustomInputGestures() {
setCustomInputGestures(inputGestures = retrieveCustomInputGestures())
@@ -72,24 +72,24 @@ constructor(private val userTracker: UserTracker,
} else emptyList()
}
- suspend fun addCustomInputGesture(inputGesture: InputGestureData): ShortcutCustomizationRequestResult {
+ suspend fun addCustomInputGesture(
+ inputGesture: InputGestureData
+ ): ShortcutCustomizationRequestResult {
return withContext(bgCoroutineContext) {
when (val result = inputManager.addCustomInputGesture(inputGesture)) {
CUSTOM_INPUT_GESTURE_RESULT_SUCCESS -> {
refreshCustomInputGestures()
SUCCESS
}
- CUSTOM_INPUT_GESTURE_RESULT_ERROR_ALREADY_EXISTS ->
- ERROR_RESERVED_COMBINATION
+ CUSTOM_INPUT_GESTURE_RESULT_ERROR_ALREADY_EXISTS -> ERROR_RESERVED_COMBINATION
- CUSTOM_INPUT_GESTURE_RESULT_ERROR_RESERVED_GESTURE ->
- ERROR_RESERVED_COMBINATION
+ CUSTOM_INPUT_GESTURE_RESULT_ERROR_RESERVED_GESTURE -> ERROR_RESERVED_COMBINATION
else -> {
Log.w(
TAG,
"Attempted to add inputGesture: $inputGesture " +
- "but ran into an error with code: $result",
+ "but ran into an error with code: $result",
)
ERROR_OTHER
}
@@ -97,11 +97,11 @@ constructor(private val userTracker: UserTracker,
}
}
- suspend fun deleteCustomInputGesture(inputGesture: InputGestureData): ShortcutCustomizationRequestResult {
- return withContext(bgCoroutineContext){
- when (
- val result = inputManager.removeCustomInputGesture(inputGesture)
- ) {
+ suspend fun deleteCustomInputGesture(
+ inputGesture: InputGestureData
+ ): ShortcutCustomizationRequestResult {
+ return withContext(bgCoroutineContext) {
+ when (val result = inputManager.removeCustomInputGesture(inputGesture)) {
CUSTOM_INPUT_GESTURE_RESULT_SUCCESS -> {
refreshCustomInputGestures()
SUCCESS
@@ -110,7 +110,7 @@ constructor(private val userTracker: UserTracker,
Log.w(
TAG,
"Attempted to delete inputGesture: $inputGesture " +
- "but ran into an error with code: $result",
+ "but ran into an error with code: $result",
)
ERROR_OTHER
}
@@ -134,7 +134,10 @@ constructor(private val userTracker: UserTracker,
}
}
+ suspend fun getInputGestureByTrigger(trigger: InputGestureData.Trigger): InputGestureData? =
+ withContext(bgCoroutineContext) { inputManager.getInputGesture(trigger) }
+
private companion object {
private const val TAG = "CustomInputGesturesRepository"
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt
index 18ca877775df..6ae948d2da2e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyboard.shortcut.data.repository
import android.hardware.input.InputGestureData
import android.hardware.input.InputGestureData.Builder
+import android.hardware.input.InputGestureData.Trigger
import android.hardware.input.InputGestureData.createKeyTrigger
import android.hardware.input.InputManager
import android.hardware.input.KeyGestureEvent.KeyGestureType
@@ -175,6 +176,11 @@ constructor(
return customInputGesturesRepository.resetAllCustomInputGestures()
}
+ suspend fun isSelectedKeyCombinationAvailable(): Boolean {
+ val trigger = buildTriggerFromSelectedKeyCombination() ?: return false
+ return customInputGesturesRepository.getInputGestureByTrigger(trigger) == null
+ }
+
private fun Builder.addKeyGestureTypeForShortcutBeingCustomized(): Builder {
val keyGestureType = getKeyGestureTypeForShortcutBeingCustomized()
@@ -222,7 +228,10 @@ constructor(
)
}
- private fun Builder.addTriggerFromSelectedKeyCombination(): Builder {
+ private fun Builder.addTriggerFromSelectedKeyCombination(): Builder =
+ setTrigger(buildTriggerFromSelectedKeyCombination())
+
+ private fun buildTriggerFromSelectedKeyCombination(): Trigger? {
val selectedKeyCombination = _selectedKeyCombination.value
if (selectedKeyCombination?.keyCode == null) {
Log.w(
@@ -230,16 +239,14 @@ constructor(
"User requested to set shortcut but selected key combination is " +
"$selectedKeyCombination",
)
- return this
+ return null
}
- return setTrigger(
- createKeyTrigger(
- /* keycode = */ selectedKeyCombination.keyCode,
- /* modifierState = */ shortcutCategoriesUtils.removeUnsupportedModifiers(
- selectedKeyCombination.modifiers
- ),
- )
+ return createKeyTrigger(
+ /* keycode= */ selectedKeyCombination.keyCode,
+ /* modifierState= */ shortcutCategoriesUtils.removeUnsupportedModifiers(
+ selectedKeyCombination.modifiers
+ ),
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
index 8e4c9349c604..0908e3b5bf85 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyboard.shortcut.data.repository
import android.content.Context
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_BACK
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT
@@ -40,11 +41,13 @@ import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVI
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.Accessibility
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.AppCategories
@@ -92,6 +95,9 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS to Accessibility,
KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS to Accessibility,
KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS to Accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_TALKBACK to Accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION to Accessibility,
+ KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK to Accessibility,
)
val gestureToInternalKeyboardShortcutGroupLabelResIdMap =
@@ -144,6 +150,10 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS to R.string.shortcutHelper_category_accessibility,
KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS to R.string.shortcutHelper_category_accessibility,
KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS to R.string.shortcutHelper_category_accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_TALKBACK to R.string.shortcutHelper_category_accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION to R.string.shortcutHelper_category_accessibility,
+ KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK to
+ R.string.shortcutHelper_category_accessibility,
)
/**
@@ -192,6 +202,11 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS to R.string.group_accessibility_toggle_slow_keys,
KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS to
R.string.group_accessibility_toggle_voice_access,
+ KEY_GESTURE_TYPE_TOGGLE_TALKBACK to R.string.group_accessibility_toggle_talkback,
+ KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION to
+ R.string.group_accessibility_toggle_magnification,
+ KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK to
+ R.string.group_accessibility_activate_select_to_speak,
)
val shortcutLabelToKeyGestureTypeMap: Map<String, Int>
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/AccessibilityShortcutsSource.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/AccessibilityShortcutsSource.kt
index 0c98f81e7cef..fdb80b2e0f87 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/AccessibilityShortcutsSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/AccessibilityShortcutsSource.kt
@@ -22,11 +22,15 @@ import android.view.KeyEvent.KEYCODE_3
import android.view.KeyEvent.KEYCODE_4
import android.view.KeyEvent.KEYCODE_5
import android.view.KeyEvent.KEYCODE_6
+import android.view.KeyEvent.KEYCODE_M
+import android.view.KeyEvent.KEYCODE_S
+import android.view.KeyEvent.KEYCODE_T
import android.view.KeyEvent.KEYCODE_V
import android.view.KeyEvent.META_ALT_ON
import android.view.KeyEvent.META_META_ON
import android.view.KeyboardShortcutGroup
import android.view.KeyboardShortcutInfo
+import com.android.hardware.input.Flags.enableTalkbackAndMagnifierKeyGestures
import com.android.hardware.input.Flags.enableVoiceAccessKeyGestures
import com.android.hardware.input.Flags.keyboardA11yShortcutControl
import com.android.systemui.dagger.qualifiers.Main
@@ -106,6 +110,34 @@ class AccessibilityShortcutsSource @Inject constructor(@Main private val resourc
)
}
+ if (enableTalkbackAndMagnifierKeyGestures()) {
+ shortcuts.add(
+ // Toggle talkback:
+ // - Meta + Alt + T
+ shortcutInfo(resources.getString(R.string.group_accessibility_toggle_talkback)) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_T)
+ }
+ )
+ shortcuts.add(
+ // Toggle magnification:
+ // - Meta + Alt + M
+ shortcutInfo(
+ resources.getString(R.string.group_accessibility_toggle_magnification)
+ ) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_M)
+ }
+ )
+ shortcuts.add(
+ // Activate Select to Speak:
+ // - Meta + Alt + S
+ shortcutInfo(
+ resources.getString(R.string.group_accessibility_activate_select_to_speak)
+ ) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_S)
+ }
+ )
+ }
+
return shortcuts
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
index 5060abdda247..8bed8537b6c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt
@@ -155,9 +155,9 @@ constructor(@Main private val resources: Resources, private val inputManager: In
command(META_META_ON, KEYCODE_DPAD_LEFT)
},
// Take a full screenshot:
- // - Meta + Ctrl + S
+ // - Meta + S
shortcutInfo(resources.getString(R.string.group_system_full_screenshot)) {
- command(META_META_ON or META_CTRL_ON, KEYCODE_S)
+ command(META_META_ON, KEYCODE_S)
},
// Access list of system / apps shortcuts:
// - Meta + /
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt
index ef242678a8ac..1a62517ad01d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt
@@ -53,4 +53,7 @@ constructor(private val customShortcutRepository: CustomShortcutCategoriesReposi
suspend fun resetAllCustomShortcuts(): ShortcutCustomizationRequestResult {
return customShortcutRepository.resetAllCustomShortcuts()
}
+
+ suspend fun isSelectedKeyCombinationAvailable(): Boolean =
+ customShortcutRepository.isSelectedKeyCombinationAvailable()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
index bd3d46d09f5e..54e27a61ac78 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.phone.create
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
class ShortcutCustomizationDialogStarter
@@ -57,20 +58,25 @@ constructor(
private val viewModel = viewModelFactory.create()
override suspend fun onActivated(): Nothing {
- viewModel.shortcutCustomizationUiState.collect { uiState ->
- when (uiState) {
- is AddShortcutDialog,
- is DeleteShortcutDialog,
- is ResetShortcutDialog -> {
- if (dialog == null) {
- dialog = createDialog().also { it.show() }
+ coroutineScope {
+ launch {
+ viewModel.shortcutCustomizationUiState.collect { uiState ->
+ when (uiState) {
+ is AddShortcutDialog,
+ is DeleteShortcutDialog,
+ is ResetShortcutDialog -> {
+ if (dialog == null) {
+ dialog = createDialog().also { it.show() }
+ }
+ }
+ is ShortcutCustomizationUiState.Inactive -> {
+ dialog?.dismiss()
+ dialog = null
+ }
}
}
- is ShortcutCustomizationUiState.Inactive -> {
- dialog?.dismiss()
- dialog = null
- }
}
+ launch { viewModel.activate() }
}
awaitCancellation()
}
@@ -101,6 +107,7 @@ constructor(
onConfirmResetShortcut = {
coroutineScope.launch { viewModel.resetAllCustomShortcuts() }
},
+ onClearSelectedKeyCombination = { viewModel.clearSelectedKeyCombination() },
)
setDialogProperties(dialog, uiState)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt
index fa03883e2a35..ea36a10fb01a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarter.kt
@@ -24,7 +24,6 @@ import android.os.UserHandle
import android.provider.Settings
import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.layout.width
-import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@@ -36,6 +35,7 @@ import com.android.systemui.keyboard.shortcut.ui.composable.ShortcutHelper
import com.android.systemui.keyboard.shortcut.ui.composable.ShortcutHelperBottomSheet
import com.android.systemui.keyboard.shortcut.ui.composable.getWidth
import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel
+import com.android.systemui.lifecycle.rememberActivated
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
@@ -51,14 +51,13 @@ class ShortcutHelperDialogStarter
constructor(
@Application private val applicationScope: CoroutineScope,
private val shortcutHelperViewModel: ShortcutHelperViewModel,
- shortcutCustomizationDialogStarterFactory: ShortcutCustomizationDialogStarter.Factory,
+ private val shortcutCustomizationDialogStarterFactory:
+ ShortcutCustomizationDialogStarter.Factory,
private val dialogFactory: SystemUIDialogFactory,
private val activityStarter: ActivityStarter,
) : CoreStartable {
@VisibleForTesting var dialog: Dialog? = null
- private val shortcutCustomizationDialogStarter =
- shortcutCustomizationDialogStarterFactory.create()
override fun start() {
shortcutHelperViewModel.shouldShow
@@ -77,7 +76,10 @@ constructor(
content = { dialog ->
val shortcutsUiState by
shortcutHelperViewModel.shortcutsUiState.collectAsStateWithLifecycle()
- LaunchedEffect(Unit) { shortcutCustomizationDialogStarter.activate() }
+ val shortcutCustomizationDialogStarter =
+ rememberActivated(traceName = "shortcutCustomizationDialogStarter") {
+ shortcutCustomizationDialogStarterFactory.create()
+ }
ShortcutHelper(
modifier = Modifier.width(getWidth()),
shortcutsUiState = shortcutsUiState,
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
index 9d43c48ee274..66e45056989d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
@@ -18,14 +18,10 @@ package com.android.systemui.keyboard.shortcut.ui.composable
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
-import androidx.compose.foundation.border
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
@@ -40,13 +36,15 @@ import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ErrorOutline
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.focusRequester
@@ -57,6 +55,7 @@ import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type
+import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.LiveRegionMode
@@ -81,6 +80,7 @@ fun ShortcutCustomizationDialog(
onConfirmSetShortcut: () -> Unit,
onConfirmDeleteShortcut: () -> Unit,
onConfirmResetShortcut: () -> Unit,
+ onClearSelectedKeyCombination: () -> Unit,
) {
when (uiState) {
is ShortcutCustomizationUiState.AddShortcutDialog -> {
@@ -90,6 +90,7 @@ fun ShortcutCustomizationDialog(
onShortcutKeyCombinationSelected,
onCancel,
onConfirmSetShortcut,
+ onClearSelectedKeyCombination,
)
}
is ShortcutCustomizationUiState.DeleteShortcutDialog -> {
@@ -111,6 +112,7 @@ private fun AddShortcutDialog(
onShortcutKeyCombinationSelected: (KeyEvent) -> Boolean,
onCancel: () -> Unit,
onConfirmSetShortcut: () -> Unit,
+ onClearSelectedKeyCombination: () -> Unit,
) {
Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
Title(uiState.shortcutLabel)
@@ -126,6 +128,7 @@ private fun AddShortcutDialog(
onShortcutKeyCombinationSelected = onShortcutKeyCombinationSelected,
pressedKeys = uiState.pressedKeys,
onConfirmSetShortcut = onConfirmSetShortcut,
+ onClearSelectedKeyCombination = onClearSelectedKeyCombination,
)
ErrorMessageContainer(uiState.errorMessage)
DialogButtons(
@@ -249,10 +252,11 @@ private fun ErrorMessageContainer(errorMessage: String) {
lineHeight = 20.sp,
fontWeight = FontWeight.W500,
color = MaterialTheme.colorScheme.error,
- modifier = Modifier.padding(start = 24.dp).width(252.dp).semantics {
- contentDescription = errorMessage
- liveRegion = LiveRegionMode.Polite
- },
+ modifier =
+ Modifier.padding(start = 24.dp).width(252.dp).semantics {
+ contentDescription = errorMessage
+ liveRegion = LiveRegionMode.Polite
+ },
)
}
}
@@ -264,72 +268,82 @@ private fun SelectedKeyCombinationContainer(
onShortcutKeyCombinationSelected: (KeyEvent) -> Boolean,
pressedKeys: List<ShortcutKey>,
onConfirmSetShortcut: () -> Unit,
+ onClearSelectedKeyCombination: () -> Unit,
) {
- val interactionSource = remember { MutableInteractionSource() }
- val isFocused by interactionSource.collectIsFocusedAsState()
- val outlineColor =
- if (!isFocused) MaterialTheme.colorScheme.outline
- else if (shouldShowError) MaterialTheme.colorScheme.error
- else MaterialTheme.colorScheme.primary
val focusRequester = remember { FocusRequester() }
-
+ val focusManager = LocalFocusManager.current
LaunchedEffect(Unit) { focusRequester.requestFocus() }
- ClickableShortcutSurface(
- onClick = {},
- color = Color.Transparent,
- shape = RoundedCornerShape(50.dp),
+ OutlinedInputField(
modifier =
Modifier.padding(all = 16.dp)
.sizeIn(minWidth = 332.dp, minHeight = 56.dp)
- .border(width = 2.dp, color = outlineColor, shape = RoundedCornerShape(50.dp))
+ .focusRequester(focusRequester)
+ .focusProperties { canFocus = true }
.onPreviewKeyEvent { keyEvent ->
val keyEventProcessed = onShortcutKeyCombinationSelected(keyEvent)
- if (
- !keyEventProcessed &&
- keyEvent.key == Key.Enter &&
- keyEvent.type == KeyEventType.KeyUp
- ) {
- onConfirmSetShortcut()
+ if (keyEventProcessed) {
true
- } else keyEventProcessed
- }
- .focusProperties { canFocus = true } // enables keyboard focus when in touch mode
- .focusRequester(focusRequester),
- interactionSource = interactionSource,
- ) {
- Row(
- modifier = Modifier.padding(start = 24.dp, top = 16.dp, end = 16.dp, bottom = 16.dp),
- verticalAlignment = Alignment.CenterVertically,
- ) {
- if (pressedKeys.isEmpty()) {
- PressKeyPrompt()
+ } else {
+ if (keyEvent.type == KeyEventType.KeyUp) {
+ when (keyEvent.key) {
+ Key.Enter -> {
+ onConfirmSetShortcut()
+ return@onPreviewKeyEvent true
+ }
+ Key.Backspace -> {
+ onClearSelectedKeyCombination()
+ return@onPreviewKeyEvent true
+ }
+ Key.DirectionDown -> {
+ focusManager.moveFocus(FocusDirection.Down)
+ return@onPreviewKeyEvent true
+ }
+ else -> return@onPreviewKeyEvent false
+ }
+ } else false
+ }
+ },
+ trailingIcon = { ErrorIcon(shouldShowError) },
+ isError = shouldShowError,
+ placeholder = { PressKeyPrompt() },
+ content =
+ if (pressedKeys.isNotEmpty()) {
+ { PressedKeysTextContainer(pressedKeys) }
} else {
- PressedKeysTextContainer(pressedKeys)
- }
- Spacer(modifier = Modifier.weight(1f))
- if (shouldShowError) {
- Icon(
- imageVector = Icons.Default.ErrorOutline,
- contentDescription = null,
- modifier = Modifier.size(20.dp),
- tint = MaterialTheme.colorScheme.error,
- )
- }
- }
+ null
+ },
+ )
+}
+
+@Composable
+private fun ErrorIcon(shouldShowError: Boolean) {
+ if (shouldShowError) {
+ Icon(
+ imageVector = Icons.Default.ErrorOutline,
+ contentDescription = null,
+ modifier = Modifier.size(20.dp),
+ tint = MaterialTheme.colorScheme.error,
+ )
}
}
@Composable
-private fun RowScope.PressedKeysTextContainer(pressedKeys: List<ShortcutKey>) {
- pressedKeys.forEachIndexed { keyIndex, key ->
- if (keyIndex > 0) {
- ShortcutKeySeparator()
- }
- if (key is ShortcutKey.Text) {
- ShortcutTextKey(key)
- } else if (key is ShortcutKey.Icon) {
- ShortcutIconKey(key)
+private fun PressedKeysTextContainer(pressedKeys: List<ShortcutKey>) {
+ Row(
+ modifier =
+ Modifier.semantics(mergeDescendants = true) { liveRegion = LiveRegionMode.Polite },
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ pressedKeys.forEachIndexed { keyIndex, key ->
+ if (keyIndex > 0) {
+ ShortcutKeySeparator()
+ }
+ if (key is ShortcutKey.Text) {
+ ShortcutTextKey(key)
+ } else if (key is ShortcutKey.Icon) {
+ ShortcutIconKey(key)
+ }
}
}
}
@@ -346,7 +360,7 @@ private fun ShortcutKeySeparator() {
}
@Composable
-private fun RowScope.ShortcutIconKey(key: ShortcutKey.Icon) {
+private fun ShortcutIconKey(key: ShortcutKey.Icon) {
Icon(
painter =
when (key) {
@@ -354,7 +368,7 @@ private fun RowScope.ShortcutIconKey(key: ShortcutKey.Icon) {
is ShortcutKey.Icon.DrawableIcon -> rememberDrawablePainter(drawable = key.drawable)
},
contentDescription = null,
- modifier = Modifier.align(Alignment.CenterVertically).height(24.dp),
+ modifier = Modifier.height(24.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
@@ -405,7 +419,7 @@ private fun Description(text: String) {
.width(316.dp)
.wrapContentSize(Alignment.Center),
color = MaterialTheme.colorScheme.onSurfaceVariant,
- textAlign = TextAlign.Center
+ textAlign = TextAlign.Center,
)
}
@@ -473,3 +487,31 @@ private fun PlusIconContainer() {
modifier = Modifier.padding(vertical = 12.dp).size(24.dp).wrapContentSize(Alignment.Center),
)
}
+
+@Composable
+private fun OutlinedInputField(
+ content: @Composable (() -> Unit)?,
+ placeholder: @Composable () -> Unit,
+ trailingIcon: @Composable () -> Unit,
+ isError: Boolean,
+ modifier: Modifier = Modifier,
+) {
+ OutlinedTextField(
+ value = "",
+ onValueChange = {},
+ placeholder = if (content == null) placeholder else null,
+ prefix = content,
+ singleLine = true,
+ modifier = modifier,
+ trailingIcon = trailingIcon,
+ colors =
+ OutlinedTextFieldDefaults.colors()
+ .copy(
+ focusedIndicatorColor = MaterialTheme.colorScheme.primary,
+ unfocusedIndicatorColor = MaterialTheme.colorScheme.outline,
+ errorIndicatorColor = MaterialTheme.colorScheme.error,
+ ),
+ shape = RoundedCornerShape(50.dp),
+ isError = isError,
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
index 915a66c43a12..f4ba99c6a394 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
@@ -28,16 +28,17 @@ import com.android.systemui.keyboard.shared.model.ShortcutCustomizationRequestRe
import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutCustomizationInteractor
import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState.AddShortcutDialog
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState.DeleteShortcutDialog
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState.ResetShortcutDialog
+import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.res.R
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class ShortcutCustomizationViewModel
@@ -45,26 +46,12 @@ class ShortcutCustomizationViewModel
constructor(
private val context: Context,
private val shortcutCustomizationInteractor: ShortcutCustomizationInteractor,
-) {
+) : ExclusiveActivatable() {
private var keyDownEventCache: KeyEvent? = null
private val _shortcutCustomizationUiState =
MutableStateFlow<ShortcutCustomizationUiState>(ShortcutCustomizationUiState.Inactive)
- val shortcutCustomizationUiState =
- shortcutCustomizationInteractor.pressedKeys
- .map { keys ->
- // Note that Action Key is excluded as it's already displayed on the UI
- keys.filter {
- it != shortcutCustomizationInteractor.getDefaultCustomShortcutModifierKey()
- }
- }
- .combine(_shortcutCustomizationUiState) { keys, uiState ->
- if (uiState is AddShortcutDialog) {
- uiState.copy(pressedKeys = keys)
- } else {
- uiState
- }
- }
+ val shortcutCustomizationUiState = _shortcutCustomizationUiState.asStateFlow()
fun onShortcutCustomizationRequested(requestInfo: ShortcutCustomizationRequestInfo) {
shortcutCustomizationInteractor.onCustomizationRequested(requestInfo)
@@ -92,7 +79,7 @@ constructor(
fun onDialogDismissed() {
_shortcutCustomizationUiState.value = ShortcutCustomizationUiState.Inactive
shortcutCustomizationInteractor.onCustomizationRequested(null)
- shortcutCustomizationInteractor.updateUserSelectedKeyCombination(null)
+ clearSelectedKeyCombination()
}
fun onShortcutKeyCombinationSelected(keyEvent: KeyEvent): Boolean {
@@ -112,7 +99,6 @@ constructor(
suspend fun onSetShortcut() {
val result = shortcutCustomizationInteractor.confirmAndSetShortcutCurrentlyBeingCustomized()
-
_shortcutCustomizationUiState.update { uiState ->
when (result) {
ShortcutCustomizationRequestResult.SUCCESS -> ShortcutCustomizationUiState.Inactive
@@ -158,6 +144,10 @@ constructor(
}
}
+ fun clearSelectedKeyCombination() {
+ shortcutCustomizationInteractor.updateUserSelectedKeyCombination(null)
+ }
+
private fun getUiStateWithErrorMessage(
uiState: ShortcutCustomizationUiState,
errorMessage: String,
@@ -180,11 +170,41 @@ constructor(
keyDownEventCache = null
}
+ private suspend fun isSelectedKeyCombinationAvailable() =
+ shortcutCustomizationInteractor.isSelectedKeyCombinationAvailable()
+
@AssistedFactory
interface Factory {
fun create(): ShortcutCustomizationViewModel
}
+ override suspend fun onActivated(): Nothing {
+ shortcutCustomizationInteractor.pressedKeys.collect {
+ val keys = filterDefaultCustomShortcutModifierKey(it)
+ val errorMessage = getErrorMessageForPressedKeys(keys)
+
+ _shortcutCustomizationUiState.update { uiState ->
+ if (uiState is AddShortcutDialog) {
+ uiState.copy(pressedKeys = keys, errorMessage = errorMessage)
+ } else {
+ uiState
+ }
+ }
+ }
+ }
+
+ private suspend fun getErrorMessageForPressedKeys(keys: List<ShortcutKey>): String {
+ return if (keys.isEmpty() or isSelectedKeyCombinationAvailable()) {
+ ""
+ }
+ else {
+ context.getString(R.string.shortcut_customizer_key_combination_in_use_error_message)
+ }
+ }
+
+ private fun filterDefaultCustomShortcutModifierKey(keys: List<ShortcutKey>) =
+ keys.filter { it != shortcutCustomizationInteractor.getDefaultCustomShortcutModifierKey() }
+
companion object {
private val SUPPORTED_MODIFIERS =
listOf(
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt
index 26eb706da200..d0d1474524c7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt
@@ -22,7 +22,6 @@ import com.android.systemui.keyboard.stickykeys.data.repository.StickyKeysReposi
import com.android.systemui.keyboard.stickykeys.shared.model.Locked
import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flatMapLatest
@@ -38,7 +37,6 @@ constructor(
@Application applicationScope: CoroutineScope,
) {
- @OptIn(ExperimentalCoroutinesApi::class)
val indicatorContent: Flow<Map<ModifierKey, Locked>> =
keyboardRepository.isAnyKeyboardConnected
.flatMapLatest { keyboardPresent ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index f37e7685f21c..df3633be4625 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -39,6 +39,8 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.dagger.KeyguardBlueprintLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.ShadeDisplayAware
@@ -55,10 +57,8 @@ import java.util.Optional
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Binds keyguard views on startup, and also exposes methods to allow rebinding if views change */
-@ExperimentalCoroutinesApi
@SysUISingleton
class KeyguardViewConfigurator
@Inject
@@ -89,6 +89,7 @@ constructor(
private val wallpaperViewModel: WallpaperViewModel,
@Main private val mainDispatcher: CoroutineDispatcher,
private val msdlPlayer: MSDLPlayer,
+ @KeyguardBlueprintLog private val blueprintLog: LogBuffer,
) : CoreStartable {
private var rootViewHandle: DisposableHandle? = null
@@ -111,6 +112,7 @@ constructor(
keyguardBlueprintViewModel,
keyguardClockViewModel,
smartspaceViewModel,
+ blueprintLog,
)
}
if (deviceEntryUnlockTrackerViewBinder.isPresent) {
@@ -151,6 +153,7 @@ constructor(
statusBarKeyguardViewManager,
mainDispatcher,
msdlPlayer,
+ blueprintLog,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubBlurComponent.kt b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubBlurComponent.kt
new file mode 100644
index 000000000000..c0411b0013a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubBlurComponent.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.dagger
+
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubBlurProvider
+import dagger.BindsInstance
+import dagger.Subcomponent
+
+@Subcomponent
+interface GlanceableHubBlurComponent {
+ @Subcomponent.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance animation: KeyguardTransitionAnimationFlow.FlowBuilder
+ ): GlanceableHubBlurComponent
+ }
+
+ fun getBlurProvider(): GlanceableHubBlurProvider
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubTransitionModule.kt
new file mode 100644
index 000000000000..affdee89d478
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/GlanceableHubTransitionModule.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.dagger
+
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
+import com.android.systemui.keyguard.ui.viewmodel.DozingToGlanceableHubTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDozingTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToOccludedTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToGlanceableHubTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.OccludedToGlanceableHubTransitionViewModel
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+import dagger.multibindings.Multibinds
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@Module(subcomponents = [GlanceableHubBlurComponent::class])
+interface GlanceableHubTransitionModule {
+ @Multibinds fun glanceableHubTransition(): Set<GlanceableHubTransition>
+}
+
+@ExperimentalCoroutinesApi
+@Module
+interface GlanceableHubTransitionImplModule {
+ @Binds
+ @IntoSet
+ fun fromLockscreen(impl: LockscreenToGlanceableHubTransitionViewModel): GlanceableHubTransition
+
+ @Binds
+ @IntoSet
+ fun toLockScreen(impl: GlanceableHubToLockscreenTransitionViewModel): GlanceableHubTransition
+
+ @Binds
+ @IntoSet
+ fun fromOccluded(impl: OccludedToGlanceableHubTransitionViewModel): GlanceableHubTransition
+
+ @Binds
+ @IntoSet
+ fun toOccluded(impl: GlanceableHubToOccludedTransitionViewModel): GlanceableHubTransition
+
+ @Binds
+ @IntoSet
+ fun fromDream(impl: DreamingToGlanceableHubTransitionViewModel): GlanceableHubTransition
+
+ @Binds
+ @IntoSet
+ fun toDream(impl: GlanceableHubToDreamingTransitionViewModel): GlanceableHubTransition
+
+ @Binds
+ @IntoSet
+ fun fromDozing(impl: DozingToGlanceableHubTransitionViewModel): GlanceableHubTransition
+
+ @Binds
+ @IntoSet
+ fun toDozing(impl: GlanceableHubToDozingTransitionViewModel): GlanceableHubTransition
+}
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 a7a432497be6..905bbe226bb7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.dagger;
import android.app.IActivityTaskManager;
import android.app.trust.TrustManager;
import android.content.Context;
+import android.content.res.Resources;
import android.os.PowerManager;
import com.android.internal.jank.InteractionJankMonitor;
@@ -34,6 +35,7 @@ import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.CoreStartable;
+import com.android.systemui.Flags;
import com.android.systemui.animation.ActivityTransitionAnimator;
import com.android.systemui.bouncer.dagger.BouncerLoggerModule;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -59,12 +61,14 @@ import com.android.systemui.keyguard.data.repository.KeyguardRepositoryModule;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionBootInteractor;
import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule;
+import com.android.systemui.keyguard.ui.transitions.BlurConfig;
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransitionModule;
import com.android.systemui.keyguard.ui.view.AlternateBouncerWindowViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModelModule;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.process.ProcessWrapper;
+import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeDisplayAware;
@@ -94,20 +98,20 @@ import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
import java.util.concurrent.Executor;
/**
* Dagger Module providing keyguard.
*/
-@ExperimentalCoroutinesApi
@Module(subcomponents = {
KeyguardQsUserSwitchComponent.class,
KeyguardStatusBarViewComponent.class},
includes = {
DeviceEntryIconTransitionModule.class,
FalsingModule.class,
+ GlanceableHubTransitionModule.class,
+ GlanceableHubTransitionImplModule.class,
PrimaryBouncerTransitionModule.class,
PrimaryBouncerTransitionImplModule.class,
KeyguardDataQuickAffordanceModule.class,
@@ -238,6 +242,20 @@ public interface KeyguardModule {
/** */
@Provides
@SysUISingleton
+ static BlurConfig provideBlurConfig(@Main Resources resources) {
+ int minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius);
+ int maxBlurRadius =
+ Flags.notificationShadeBlur() || Flags.bouncerUiRevamp()
+ || Flags.glanceableHubBlurredBackground()
+ ? resources.getDimensionPixelSize(R.dimen.max_shade_window_blur_radius)
+ : resources.getDimensionPixelSize(R.dimen.max_window_blur_radius);
+
+ return new BlurConfig(minBlurRadius, maxBlurRadius);
+ }
+
+ /** */
+ @Provides
+ @SysUISingleton
static ThreadAssert providesThreadAssert() {
return new ThreadAssert();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt
index d3e2560d6a21..7c4dbfeba50f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt
@@ -16,11 +16,6 @@
package com.android.systemui.keyguard.dagger
-import android.content.res.Resources
-import com.android.systemui.Flags
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.keyguard.ui.transitions.BlurConfig
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToPrimaryBouncerTransitionViewModel
@@ -34,13 +29,10 @@ import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGlanceableHubT
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToOccludedTransitionViewModel
-import com.android.systemui.res.R
import dagger.Binds
import dagger.Module
-import dagger.Provides
import dagger.multibindings.IntoSet
import dagger.multibindings.Multibinds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/**
* Base module that defines the [PrimaryBouncerTransition] multibinding. All variants of SystemUI
@@ -49,28 +41,12 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
@Module
interface PrimaryBouncerTransitionModule {
@Multibinds fun primaryBouncerTransitions(): Set<PrimaryBouncerTransition>
-
- companion object {
- @Provides
- @SysUISingleton
- fun provideBlurConfig(@Main resources: Resources): BlurConfig {
- val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius)
- val maxBlurRadius =
- if (Flags.notificationShadeBlur() || Flags.bouncerUiRevamp()) {
- resources.getDimensionPixelSize(R.dimen.max_shade_window_blur_radius)
- } else {
- resources.getDimensionPixelSize(R.dimen.max_window_blur_radius)
- }
- return BlurConfig(minBlurRadius.toFloat(), maxBlurRadius.toFloat())
- }
- }
}
/**
* Module that installs all the implementations of [PrimaryBouncerTransition] from different
* keyguard states to and away from the primary bouncer.
*/
-@ExperimentalCoroutinesApi
@Module
interface PrimaryBouncerTransitionImplModule {
@Binds
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 c7749876c683..3968b49ee731 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
@@ -31,7 +31,6 @@ import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.onStart
* the question "which affordances should the keyguard show?" for the user associated with the
* System UI process.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardQuickAffordanceLocalUserSelectionManager
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManager.kt
index 8be11a4691be..ea3662bdb86a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManager.kt
@@ -28,7 +28,6 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -44,7 +43,6 @@ import com.android.app.tracing.coroutines.launchTraced as launch
* the question "which affordances should the keyguard show?" for users associated with other System
* UI processes.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardQuickAffordanceRemoteUserSelectionManager
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
index cb7702e090d0..760adbf58d93 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
@@ -38,7 +38,6 @@ import com.android.systemui.wallet.controller.QuickAccessWalletController
import com.android.systemui.wallet.util.getPaymentCards
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
@@ -63,7 +62,6 @@ constructor(
override val pickerIconResourceId = R.drawable.ic_wallet_lockscreen
- @OptIn(ExperimentalCoroutinesApi::class)
override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> =
conflatedCallbackFlow {
val callback =
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 4e7de5dd8a9c..dd2bec143292 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
@@ -50,7 +50,6 @@ import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -122,7 +121,6 @@ interface BiometricSettingsRepository {
private const val TAG = "BiometricsRepositoryImpl"
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class BiometricSettingsRepositoryImpl
@Inject
@@ -387,7 +385,6 @@ constructor(
.and(isFaceAuthSupportedInCurrentPosture)
}
-@OptIn(ExperimentalCoroutinesApi::class)
private class StrongAuthTracker(
private val userRepository: UserRepository,
@ShadeDisplayAware context: Context?
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
index b826a002b9d9..37b657fffd80 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.data.repository
import android.os.Handler
-import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
@@ -26,6 +25,9 @@ import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT
import com.android.systemui.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.KeyguardBlueprintLog
import com.android.systemui.util.ThreadAssert
import java.io.PrintWriter
import java.util.TreeMap
@@ -51,7 +53,10 @@ constructor(
blueprints: Set<@JvmSuppressWildcards KeyguardBlueprint>,
@Main val handler: Handler,
val assert: ThreadAssert,
+ @KeyguardBlueprintLog log: LogBuffer,
) {
+ private val logger = Logger(log, "KeyguardBlueprintRepository")
+
// This is TreeMap so that we can order the blueprints and assign numerical values to the
// blueprints in the adb tool.
private val blueprintIdMap: TreeMap<String, KeyguardBlueprint> =
@@ -69,11 +74,12 @@ constructor(
fun applyBlueprint(blueprintId: String?): Boolean {
val blueprint = blueprintIdMap[blueprintId]
if (blueprint == null) {
- Log.e(
- TAG,
- "Could not find blueprint with id: $blueprintId. " +
+ logger.e({
+ "Could not find blueprint with id: $str1. " +
"Perhaps it was not added to KeyguardBlueprintModule?"
- )
+ }) {
+ str1 = blueprintId
+ }
return false
}
@@ -99,7 +105,9 @@ constructor(
targetTransitionConfig?.let {
val success = refreshTransition.tryEmit(it)
if (!success) {
- Log.e(TAG, "refreshBlueprint: Failed to emit blueprint refresh: $it")
+ logger.e({ "refreshBlueprint: Failed to emit blueprint refresh: $str1" }) {
+ str1 = "$it"
+ }
}
}
targetTransitionConfig = null
@@ -110,6 +118,8 @@ constructor(
if ((targetTransitionConfig?.type?.priority ?: Int.MIN_VALUE) < config.type.priority) {
if (targetTransitionConfig == null) scheduleCallback()
targetTransitionConfig = config
+ } else {
+ logger.i({ "Skipping low priority transition: $str1" }) { str1 = "$config" }
}
}
@@ -117,8 +127,4 @@ constructor(
fun printBlueprints(pw: PrintWriter) {
blueprintIdMap.onEachIndexed { index, entry -> pw.println("$index: ${entry.key}") }
}
-
- companion object {
- private const val TAG = "KeyguardBlueprintRepository"
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
index c1ec88bb44f1..aa28c5b90090 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
@@ -41,7 +41,6 @@ import com.android.systemui.util.kotlin.FlowDumperImpl
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -53,7 +52,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Abstracts access to application state related to keyguard quick affordances. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardQuickAffordanceRepository
@Inject
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 11477fb6cad1..621cc4666d31 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
@@ -50,7 +50,6 @@ import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -535,7 +534,6 @@ constructor(
awaitClose { dozeTransitionListener.removeCallback(callback) }
}
- @OptIn(ExperimentalCoroutinesApi::class)
override val isEncryptedOrLockdown: Flow<Boolean> =
conflatedCallbackFlow {
val callback =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
index 4f6319af24f1..0871f13d490b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.data.repository
import android.content.Context
@@ -37,7 +35,6 @@ import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.statusbar.PowerButtonReveal
import javax.inject.Inject
import kotlin.math.max
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
index bd5d096b4f6a..c5a6fa199c58 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
@@ -31,7 +31,6 @@ import com.android.systemui.user.data.repository.UserRepository
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -71,7 +70,6 @@ interface TrustRepository {
suspend fun reportKeyguardShowingChanged()
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class TrustRepositoryImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt
index ebc348388b40..056d365cd4b3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt
@@ -15,10 +15,8 @@ import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.StateFlow
-@ExperimentalCoroutinesApi
@SysUISingleton
class BiometricUnlockInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt
index 68ec4f3e86ce..ccff49ac0bde 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt
@@ -28,7 +28,6 @@ import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -40,7 +39,6 @@ import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
/** Encapsulates business-logic related to Ambient Display burn-in offsets. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class BurnInInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DevicePostureInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DevicePostureInteractor.kt
index e48cddb33aa4..8af173670d3e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DevicePostureInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DevicePostureInteractor.kt
@@ -19,10 +19,8 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.DevicePostureRepository
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** DevicePosture business logic. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class DevicePostureInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index 717437923e57..4ad04bef6836 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -193,7 +193,10 @@ constructor(
if (SceneContainerFlag.isEnabled) return
scope.launch("$TAG#listenForAodToPrimaryBouncer") {
keyguardInteractor.primaryBouncerShowing
- .filterRelevantKeyguardStateAnd { primaryBouncerShowing -> primaryBouncerShowing }
+ .filterRelevantKeyguardStateAnd { primaryBouncerShowing ->
+ !isWakeAndUnlock(keyguardInteractor.biometricUnlockState.value.mode) &&
+ primaryBouncerShowing
+ }
.collect { startTransitionTo(KeyguardState.PRIMARY_BOUNCER) }
}
}
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 82b8ca2a890b..251af11f7fe6 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
@@ -44,12 +44,10 @@ import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class FromDreamingTransitionInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
index 3565b612a3c9..c5d40a0dcf30 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
@@ -48,7 +48,6 @@ import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
-import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext
@OptIn(FlowPreview::class)
@@ -92,6 +91,7 @@ constructor(
listenForHubToAlternateBouncer()
listenForHubToOccluded()
listenForHubToGone()
+ listenForHubToDreaming()
}
override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator {
@@ -177,6 +177,24 @@ constructor(
}
}
+ private fun listenForHubToDreaming() {
+ if (!communalSettingsInteractor.isV2FlagEnabled()) {
+ return
+ }
+
+ scope.launch {
+ keyguardInteractor.isAbleToDream
+ .filterRelevantKeyguardStateAnd { isAbleToDream -> isAbleToDream }
+ .collect {
+ communalSceneInteractor.changeScene(
+ newScene = CommunalScenes.Blank,
+ loggingReason = "hub to dreaming",
+ keyguardState = KeyguardState.DREAMING,
+ )
+ }
+ }
+ }
+
private fun listenForHubToOccluded() {
if (KeyguardWmStateRefactor.isEnabled) {
scope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
index 2aaec8797cbe..fc79c7ff118d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
@@ -15,8 +15,6 @@
*
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.domain.interactor
import com.android.app.tracing.coroutines.launchTraced as launch
@@ -37,7 +35,6 @@ import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
index cc8652c76181..d8c707f9baeb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
@@ -36,7 +36,6 @@ import com.android.systemui.shade.domain.interactor.ShadeInteractor
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
@@ -52,7 +51,6 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
/** Encapsulates business-logic for actions to run when the keyguard is dismissed. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class KeyguardDismissActionInteractor
@Inject
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 1f3c08ca9f7a..75178f0ffef0 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
@@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.domain.interactor
import android.app.StatusBarManager
@@ -55,7 +53,6 @@ import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt
index 2d81be6fb0dc..6d9b276031e9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt
@@ -32,10 +32,8 @@ import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Handles key events arriving when the keyguard is showing or device is dozing. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class KeyguardKeyEventInteractor
@Inject
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 b866fcab2893..de5088c3521c 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
@@ -61,7 +61,6 @@ import com.android.systemui.statusbar.policy.KeyguardStateController
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -73,7 +72,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardQuickAffordanceInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt
index a6503005f8fd..705eaa22aa9a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt
@@ -38,7 +38,6 @@ import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
@@ -53,7 +52,6 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
/** Business logic for use-cases related to top-level touch handling in the lock screen. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardTouchHandlingInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt
index b986d56e9a82..2154564503fb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt
@@ -28,7 +28,6 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
@@ -51,7 +50,6 @@ constructor(
* Whether the lockscreen should be showing when the device starts up for the first time. If not
* then we'll seed the repository with a transition from OFF -> GONE.
*/
- @OptIn(ExperimentalCoroutinesApi::class)
private val showLockscreenOnBoot: Flow<Boolean> by lazy {
deviceProvisioningInteractor.isDeviceProvisioned.map { provisioned ->
(provisioned || deviceEntryInteractor.isAuthenticationRequired()) &&
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 f078fe26902e..58fb4230ccf5 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
@@ -41,7 +41,6 @@ import com.android.systemui.util.kotlin.WithPrev
import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.channels.BufferOverflow
@@ -65,7 +64,6 @@ import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
/** Encapsulates business-logic related to the keyguard transitions. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardTransitionInteractor
@Inject
@@ -127,7 +125,7 @@ constructor(
repository.transitions
.pairwise()
.filter { it.newValue.transitionState == TransitionState.STARTED }
- .shareIn(scope, SharingStarted.Eagerly)
+ .shareIn(scope, SharingStarted.Eagerly, replay = 1)
init {
// Collect non-canceled steps and emit transition values.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
index 6d9c6a666f56..8429c23d2018 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
@@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.domain.interactor
import com.android.keyguard.logging.ScrimLogger
@@ -34,7 +32,6 @@ import com.android.systemui.util.kotlin.sample
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
index 63bfba604b76..4d8667768697 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
@@ -26,14 +26,12 @@ import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.hideAffordancesRequest
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
/** Encapsulates business logic for transitions between UDFPS states on the keyguard. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class UdfpsKeyguardInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
index 184f30237e8d..61cf2cdab92d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.domain.interactor
import com.android.compose.animation.scene.ObservableTransitionState.Idle
@@ -24,7 +22,6 @@ import com.android.systemui.Flags.transitionRaceCondition
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.Companion.deviceIsAsleepInState
@@ -35,11 +32,9 @@ import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor
import com.android.systemui.util.kotlin.Utils.Companion.toQuad
-import com.android.systemui.util.kotlin.sample
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import dagger.Lazy
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -47,7 +42,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class WindowManagerLockscreenVisibilityInteractor
@Inject
@@ -84,7 +78,6 @@ constructor(
* only be visible after swiping 20% of the way up the screen, and should become invisible again
* if the user swipes back down.
*/
- @OptIn(ExperimentalCoroutinesApi::class)
private val transitionSpecificSurfaceBehindVisibility: Flow<Boolean?> =
transitionInteractor.startedKeyguardTransitionStep
.flatMapLatest { startedStep ->
@@ -122,7 +115,6 @@ constructor(
* transitioning between [KeyguardState]s or [Scenes] or the transition-specific visibility used
* during certain ongoing transitions.
*/
- @OptIn(ExperimentalCoroutinesApi::class)
val surfaceBehindVisibility: Flow<Boolean> =
if (SceneContainerFlag.isEnabled) {
sceneInteractor.get().transitionState.flatMapLatestConflated { state ->
@@ -239,12 +231,12 @@ constructor(
private val lockscreenVisibilityLegacy =
combine(
transitionInteractor.currentKeyguardState,
+ transitionInteractor.startedStepWithPrecedingStep,
wakeToGoneInteractor.canWakeDirectlyToGone,
surfaceBehindVisibility,
- ::Triple,
+ ::toQuad,
)
- .sample(transitionInteractor.startedStepWithPrecedingStep, ::toQuad)
- .map { (currentState, canWakeDirectlyToGone, surfaceBehindVis, startedWithPrev) ->
+ .map { (currentState, startedWithPrev, canWakeDirectlyToGone, surfaceBehindVis) ->
val startedFromStep = startedWithPrev.previousValue
val startedStep = startedWithPrev.newValue
val returningToGoneAfterCancellation =
@@ -331,17 +323,9 @@ constructor(
* clock/smartspace/notif icons are visible.
*/
val aodVisibility: Flow<Boolean> =
- combine(
- keyguardInteractor.isDozing,
- keyguardInteractor.isAodAvailable,
- keyguardInteractor.biometricUnlockState,
- ) { isDozing, isAodAvailable, biometricUnlockState ->
- // AOD is visible if we're dozing, unless we are wake and unlocking (where we go
- // directly from AOD to unlocked while dozing).
- isDozing &&
- isAodAvailable &&
- !BiometricUnlockMode.isWakeAndUnlock(biometricUnlockState.mode)
- }
+ transitionInteractor
+ .transitionValue(KeyguardState.AOD)
+ .map { it == 1f }
.distinctUntilChanged()
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt
index 23b7b664d4f1..62e8474fe24b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerMessageAreaViewBinder.kt
@@ -22,10 +22,8 @@ import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.keyguard.AuthKeyguardMessageArea
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Binds the alternate bouncer message view to its view-model. */
-@ExperimentalCoroutinesApi
object AlternateBouncerMessageAreaViewBinder {
/** Binds the view to the view-model, continuing to update the former based on the latter. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt
index 6ef9863f1112..0b587ae1f58e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerUdfpsViewBinder.kt
@@ -26,9 +26,7 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-@ExperimentalCoroutinesApi
object AlternateBouncerUdfpsViewBinder {
/** Updates UI for the UDFPS icon on the alternate bouncer. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
index 33783b515763..fa64fc07aad9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -47,7 +47,6 @@ import com.android.systemui.scrim.ScrimView
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/**
* When necessary, adds the alternate bouncer window above most other windows (including the
@@ -56,7 +55,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
*
* For devices that support UDFPS, this view includes a UDFPS view.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class AlternateBouncerViewBinder
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
index 3d6cf2f9d1c1..e9a3bd62b9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
@@ -41,10 +41,8 @@ import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.util.kotlin.DisposableHandles
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import com.android.app.tracing.coroutines.launchTraced as launch
-@ExperimentalCoroutinesApi
object DeviceEntryIconViewBinder {
private const val TAG = "DeviceEntryIconViewBinder"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
index 261c130d0d82..5c4e34e31d58 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.ui.binder
-import android.util.Log
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
@@ -25,13 +24,16 @@ import androidx.lifecycle.repeatOnLifecycle
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.customization.R as customR
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
-import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.BaseBlueprintTransition
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.KeyguardBlueprintLog
+import com.android.systemui.plugins.clocks.ClockLogger.Companion.getVisText
import com.android.systemui.shared.R as sharedR
import com.android.systemui.util.kotlin.pairwise
@@ -42,7 +44,9 @@ object KeyguardBlueprintViewBinder {
viewModel: KeyguardBlueprintViewModel,
clockViewModel: KeyguardClockViewModel,
smartspaceViewModel: KeyguardSmartspaceViewModel,
+ @KeyguardBlueprintLog log: LogBuffer,
) {
+ val logger = Logger(log, TAG)
constraintLayout.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch("$TAG#viewModel.blueprint") {
@@ -54,6 +58,7 @@ object KeyguardBlueprintViewBinder {
config,
clockViewModel,
smartspaceViewModel,
+ log,
)
viewModel.runTransition(constraintLayout, transition, config) {
@@ -74,7 +79,7 @@ object KeyguardBlueprintViewBinder {
blueprint.applyConstraints(this)
}
- logAlphaVisibilityScaleOfAppliedConstraintSet(cs, clockViewModel)
+ logger.logConstraintSet(cs, clockViewModel)
cs.applyTo(constraintLayout)
}
}
@@ -97,7 +102,7 @@ object KeyguardBlueprintViewBinder {
clone(constraintLayout)
blueprint.applyConstraints(this)
}
- logAlphaVisibilityScaleOfAppliedConstraintSet(cs, clockViewModel)
+ logger.logConstraintSet(cs, clockViewModel)
cs.applyTo(constraintLayout)
}
}
@@ -106,35 +111,33 @@ object KeyguardBlueprintViewBinder {
}
}
- private fun logAlphaVisibilityScaleOfAppliedConstraintSet(
- cs: ConstraintSet,
- viewModel: KeyguardClockViewModel,
- ) {
+ private fun Logger.logConstraintSet(cs: ConstraintSet, viewModel: KeyguardClockViewModel) {
val currentClock = viewModel.currentClock.value
- if (!DEBUG || currentClock == null) return
- val smallClockViewId = customR.id.lockscreen_clock_view
- val largeClockViewId = currentClock.largeClock.layout.views[0].id
- val smartspaceDateId = sharedR.id.date_smartspace_view
- Log.i(
- TAG,
- "applyCsToSmallClock: vis=${cs.getVisibility(smallClockViewId)} " +
- "alpha=${cs.getConstraint(smallClockViewId).propertySet.alpha} " +
- "scale=${cs.getConstraint(smallClockViewId).transform.scaleX} ",
- )
- Log.i(
- TAG,
- "applyCsToLargeClock: vis=${cs.getVisibility(largeClockViewId)} " +
- "alpha=${cs.getConstraint(largeClockViewId).propertySet.alpha} " +
- "scale=${cs.getConstraint(largeClockViewId).transform.scaleX} " +
- "pivotX=${cs.getConstraint(largeClockViewId).transform.transformPivotX} ",
- )
- Log.i(
- TAG,
- "applyCsToSmartspaceDate: vis=${cs.getVisibility(smartspaceDateId)} " +
- "alpha=${cs.getConstraint(smartspaceDateId).propertySet.alpha}",
- )
+ if (currentClock == null) return
+
+ this.i({ "applyCsToSmallClock: vis=${getVisText(int1)}; alpha=$str1; scale=$str2" }) {
+ val smallClockViewId = customR.id.lockscreen_clock_view
+ int1 = cs.getVisibility(smallClockViewId)
+ str1 = "${cs.getConstraint(smallClockViewId).propertySet.alpha}"
+ str2 = "${cs.getConstraint(smallClockViewId).transform.scaleX}"
+ }
+
+ this.i({
+ "applyCsToLargeClock: vis=${getVisText(int1)}; alpha=$str1; scale=$str2; pivotX=$str3"
+ }) {
+ val largeClockViewId = currentClock.largeClock.layout.views[0].id
+ int1 = cs.getVisibility(largeClockViewId)
+ str1 = "${cs.getConstraint(largeClockViewId).propertySet.alpha}"
+ str2 = "${cs.getConstraint(largeClockViewId).transform.scaleX}"
+ str3 = "${cs.getConstraint(largeClockViewId).transform.transformPivotX}"
+ }
+
+ this.i({ "applyCsToSmartspaceDate: vis=${getVisText(int1)}; alpha=$str1" }) {
+ val smartspaceDateId = sharedR.id.date_smartspace_view
+ int1 = cs.getVisibility(smartspaceDateId)
+ str1 = "${cs.getConstraint(smartspaceDateId).propertySet.alpha}"
+ }
}
- private const val TAG = "KeyguardBlueprintViewBinder"
- private const val DEBUG = false
+ private val TAG = "KeyguardBlueprintViewBinder"
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
index f1a316c3d4fa..7a08dbd50daa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
@@ -23,11 +23,9 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInte
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import com.android.app.tracing.coroutines.launchTraced as launch
/** Runs actions on keyguard dismissal. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardDismissActionBinder
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
index 21c9b0b82b2d..1a8bf001e0c1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt
@@ -30,7 +30,6 @@ import com.android.systemui.res.R
import com.android.systemui.statusbar.KeyguardIndicationController
import com.android.systemui.util.kotlin.DisposableHandles
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
@@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.map
* view-binding, binding each view only once. It is okay and expected for the same instance of the
* view-model to be reused for multiple view/view-binder bindings.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
object KeyguardIndicationAreaBinder {
/** Binds the view to the view-model, continuing to update the former based on the latter. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index d8bd4452f2a6..70a52afeb8c2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -22,7 +22,6 @@ import android.annotation.DrawableRes
import android.annotation.SuppressLint
import android.graphics.Point
import android.graphics.Rect
-import android.util.Log
import android.view.HapticFeedbackConstants
import android.view.InputDevice
import android.view.MotionEvent
@@ -65,6 +64,9 @@ import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessage
import com.android.systemui.keyguard.ui.viewmodel.TransitionData
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.KeyguardBlueprintLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -86,14 +88,12 @@ import com.google.android.msdl.domain.MSDLPlayer
import kotlin.math.min
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
/** Bind occludingAppDeviceEntryMessageViewModel to run whenever the keyguard view is attached. */
-@OptIn(ExperimentalCoroutinesApi::class)
object KeyguardRootViewBinder {
@SuppressLint("ClickableViewAccessibility")
@JvmStatic
@@ -117,6 +117,7 @@ object KeyguardRootViewBinder {
statusBarKeyguardViewManager: StatusBarKeyguardViewManager?,
mainImmediateDispatcher: CoroutineDispatcher,
msdlPlayer: MSDLPlayer?,
+ @KeyguardBlueprintLog blueprintLog: LogBuffer,
): DisposableHandle {
val disposables = DisposableHandles()
val childViews = mutableMapOf<Int, View>()
@@ -406,6 +407,7 @@ object KeyguardRootViewBinder {
clockViewModel,
childViews,
burnInParams,
+ Logger(blueprintLog, TAG),
)
)
@@ -463,6 +465,7 @@ object KeyguardRootViewBinder {
private val clockViewModel: KeyguardClockViewModel,
private val childViews: Map<Int, View>,
private val burnInParams: MutableStateFlow<BurnInParameters>,
+ private val logger: Logger,
) : OnLayoutChangeListener {
var prevTransition: TransitionData? = null
@@ -483,7 +486,7 @@ object KeyguardRootViewBinder {
val transition = blueprintViewModel.currentTransition.value
val shouldAnimate = transition != null && transition.config.type.animateNotifChanges
if (prevTransition == transition && shouldAnimate) {
- if (DEBUG) Log.w(TAG, "Skipping; layout during transition")
+ logger.w("Skipping; layout during transition")
return
}
@@ -573,5 +576,4 @@ object KeyguardRootViewBinder {
private const val ID = "occluding_app_device_entry_unlock_msg"
private const val AOD_ICONS_APPEAR_DURATION: Long = 200
private const val TAG = "KeyguardRootViewBinder"
- private const val DEBUG = false
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt
index 13c2ffb70220..220846d08de7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt
@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.ui.binder
import android.graphics.Rect
+import android.util.TypedValue
import android.view.View
import android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED
import android.widget.TextView
@@ -101,6 +102,13 @@ object KeyguardSettingsViewBinder {
}
}
}
+
+ launch("$TAG#viewModel.textSize") {
+ viewModel.textSize.collect { textSize ->
+ val textView: TextView = view.requireViewById(R.id.text)
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize.toFloat())
+ }
+ }
}
}
return disposableHandle
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 7605bdd3d7b5..cff5cebf2011 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -86,7 +86,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
@@ -95,7 +94,6 @@ import org.json.JSONObject
/** Renders the preview of the lock screen. */
class KeyguardPreviewRenderer
-@OptIn(ExperimentalCoroutinesApi::class)
@AssistedInject
constructor(
@Application private val context: Context,
@@ -323,7 +321,6 @@ constructor(
smartSpaceView?.alpha = if (shouldHighlightSelectedAffordance) DIM_ALPHA else 1.0f
}
- @OptIn(ExperimentalCoroutinesApi::class)
private fun setupKeyguardRootView(previewContext: Context, rootView: FrameLayout) {
val keyguardRootView = KeyguardRootView(previewContext, null)
rootView.addView(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
index e2ad46353c51..dba2578f79da 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
@@ -57,9 +57,7 @@ import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTran
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoSet
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-@ExperimentalCoroutinesApi
@Module
abstract class DeviceEntryIconTransitionModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubBlurProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubBlurProvider.kt
new file mode 100644
index 000000000000..19cd501fa787
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubBlurProvider.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.transitions
+
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * {@link GlanceableHubBlurProvider} helps provide a consistent blur experience across glanceable
+ * hub transitions by defining a single point where both the exit and entry flows are defined. Note
+ * that since these flows are driven by the specific transition animations, a singleton provider
+ * cannot be used.
+ */
+class GlanceableHubBlurProvider
+@Inject
+constructor(
+ transitionAnimation: KeyguardTransitionAnimationFlow.FlowBuilder,
+ blurConfig: BlurConfig,
+) {
+ val exitBlurRadius: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx)
+
+ val enterBlurRadius: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubTransition.kt
new file mode 100644
index 000000000000..1cc81f0cc90d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/GlanceableHubTransition.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.transitions
+
+import kotlinx.coroutines.flow.Flow
+
+interface GlanceableHubTransition {
+ /** Radius of blur applied to the window's root view. */
+ val windowBlurRadius: Flow<Float>
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/InWindowLauncherUnlockAnimationManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/InWindowLauncherUnlockAnimationManager.kt
index eb005f226cf1..454ba9af5745 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/InWindowLauncherUnlockAnimationManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/InWindowLauncherUnlockAnimationManager.kt
@@ -76,9 +76,8 @@ constructor(
private var manualUnlockAmount: Float? = null
/**
- * Called from [OverviewProxyService] to provide us with the launcher unlock animation
- * controller, which can be used to start and update the unlock animation in the launcher
- * process.
+ * Called from Launcher to provide us with the launcher unlock animation controller, which can
+ * be used to start and update the unlock animation in the launcher process.
*/
override fun setLauncherUnlockController(
activityClass: String,
@@ -117,7 +116,7 @@ constructor(
launcher.prepareForUnlock(
false,
Rect(),
- 0
+ 0,
) // TODO(b/293894758): Add smartspace animation support.
}
}
@@ -134,14 +133,14 @@ constructor(
Log.e(
TAG,
"Called prepareForUnlock(), but not playUnlockAnimation(). " +
- "Failing-safe by calling setUnlockAmount(1f)"
+ "Failing-safe by calling setUnlockAmount(1f)",
)
setUnlockAmount(1f, forceIfAnimating = true)
} else if (manualUnlockSetButNotFullyVisible) {
Log.e(
TAG,
"Unlock has ended, but manual unlock amount != 1f. " +
- "Failing-safe by calling setUnlockAmount(1f)"
+ "Failing-safe by calling setUnlockAmount(1f)",
)
setUnlockAmount(1f, forceIfAnimating = true)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
index 82abb05177e1..af323390073b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -39,14 +39,12 @@ import java.util.Optional
import javax.inject.Inject
import javax.inject.Named
import kotlin.jvm.optionals.getOrNull
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/**
* Positions elements of the lockscreen to the default position.
*
* This will be the most common use case for phones in portrait mode.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
@JvmSuppressWildcards
class DefaultKeyguardBlueprint
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt
index 9a55f7bab33b..0fb1af3e232d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt
@@ -22,11 +22,13 @@ import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSi
import com.android.systemui.keyguard.ui.view.layout.sections.transitions.DefaultClockSteppingTransition
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
+import com.android.systemui.log.LogBuffer
class IntraBlueprintTransition(
config: IntraBlueprintTransition.Config,
clockViewModel: KeyguardClockViewModel,
smartspaceViewModel: KeyguardSmartspaceViewModel,
+ logBuffer: LogBuffer,
) : TransitionSet() {
enum class Type(val priority: Int, val animateNotifChanges: Boolean) {
@@ -63,7 +65,7 @@ class IntraBlueprintTransition(
addTransition(
clockViewModel.currentClock.value?.let { DefaultClockSteppingTransition(it) }
)
- else -> addTransition(ClockSizeTransition(config, clockViewModel))
+ else -> addTransition(ClockSizeTransition(config, clockViewModel, logBuffer))
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index e8fce9ca4aa8..0c7e865a84a4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -21,7 +21,6 @@ import android.content.Context
import android.graphics.Point
import android.graphics.Rect
import android.util.DisplayMetrics
-import android.util.Log
import android.view.WindowManager
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.widget.ConstraintLayout
@@ -39,6 +38,8 @@ import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.KeyguardBlueprintLog
import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
@@ -49,10 +50,8 @@ import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Includes the device entry icon. */
-@ExperimentalCoroutinesApi
class DefaultDeviceEntrySection
@Inject
constructor(
@@ -68,7 +67,9 @@ constructor(
private val falsingManager: Lazy<FalsingManager>,
private val vibratorHelper: Lazy<VibratorHelper>,
@LongPressTouchLog private val logBuffer: LogBuffer,
+ @KeyguardBlueprintLog blueprintLogBuffer: LogBuffer,
) : KeyguardSection() {
+ private val blueprintLogger = Logger(blueprintLogBuffer, TAG)
private val deviceEntryIconViewId = R.id.device_entry_icon_view
private var disposableHandle: DisposableHandle? = null
@@ -101,11 +102,8 @@ constructor(
}
override fun applyConstraints(constraintSet: ConstraintSet) {
- Log.d(
- "DefaultDeviceEntrySection",
- "isUdfpsSupported=${deviceEntryIconViewModel.get().isUdfpsSupported.value}",
- )
val isUdfpsSupported = deviceEntryIconViewModel.get().isUdfpsSupported.value
+ blueprintLogger.d({ "isUdfpsSupported=$bool1" }) { bool1 = isUdfpsSupported }
val scaleFactor: Float = authController.scaleFactor
val mBottomPaddingPx =
@@ -126,12 +124,13 @@ constructor(
if (isUdfpsSupported) {
deviceEntryIconViewModel.get().udfpsLocation.value?.let { udfpsLocation ->
- Log.d(
- "DeviceEntrySection",
- "udfpsLocation=$udfpsLocation, " +
- "scaledLocation=(${udfpsLocation.centerX},${udfpsLocation.centerY}), " +
- "unusedAuthController=${authController.udfpsLocation}",
- )
+ blueprintLogger.d({
+ "udfpsLocation=$str1, scaledLocation=$str2, unusedAuthController=$str3"
+ }) {
+ str1 = "$udfpsLocation"
+ str2 = "(${udfpsLocation.centerX}, ${udfpsLocation.centerY})"
+ str3 = "${authController.udfpsLocation}"
+ }
centerIcon(
Point(udfpsLocation.centerX.toInt(), udfpsLocation.centerY.toInt()),
udfpsLocation.radius,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultUdfpsAccessibilityOverlaySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultUdfpsAccessibilityOverlaySection.kt
index 8186aa3746cf..c48fc535023c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultUdfpsAccessibilityOverlaySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultUdfpsAccessibilityOverlaySection.kt
@@ -27,10 +27,8 @@ import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Positions the UDFPS accessibility overlay on the bottom half of the keyguard. */
-@ExperimentalCoroutinesApi
class DefaultUdfpsAccessibilityOverlaySection
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
index 29bda7623675..fdd9355805b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
@@ -24,7 +24,6 @@ import android.transition.Transition
import android.transition.TransitionListenerAdapter
import android.transition.TransitionSet
import android.transition.TransitionValues
-import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver.OnPreDrawListener
@@ -35,6 +34,9 @@ import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.Intra
import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.SmartspaceMoveTransition.Companion.STATUS_AREA_MOVE_DOWN_MILLIS
import com.android.systemui.keyguard.ui.view.layout.sections.transitions.ClockSizeTransition.SmartspaceMoveTransition.Companion.STATUS_AREA_MOVE_UP_MILLIS
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.plugins.clocks.ClockLogger.Companion.getVisText
import com.android.systemui.res.R
import com.android.systemui.shared.R as sharedR
import com.google.android.material.math.MathUtils
@@ -48,19 +50,21 @@ internal fun View.setRect(rect: Rect) =
class ClockSizeTransition(
config: IntraBlueprintTransition.Config,
clockViewModel: KeyguardClockViewModel,
+ logBuffer: LogBuffer,
) : TransitionSet() {
+
init {
ordering = ORDERING_TOGETHER
if (config.type != Type.SmartspaceVisibility) {
- addTransition(ClockFaceOutTransition(config, clockViewModel))
- addTransition(ClockFaceInTransition(config, clockViewModel))
+ addTransition(ClockFaceOutTransition(config, clockViewModel, logBuffer))
+ addTransition(ClockFaceInTransition(config, clockViewModel, logBuffer))
}
- addTransition(SmartspaceMoveTransition(config, clockViewModel))
+ addTransition(SmartspaceMoveTransition(config, clockViewModel, logBuffer))
}
- abstract class VisibilityBoundsTransition() : Transition() {
+ abstract class VisibilityBoundsTransition(logBuffer: LogBuffer) : Transition() {
+ protected val logger = Logger(logBuffer, this::class.simpleName!!)
abstract val captureSmartspace: Boolean
- protected val TAG = this::class.simpleName!!
override fun captureEndValues(transition: TransitionValues) = captureValues(transition)
@@ -80,7 +84,9 @@ class ClockSizeTransition(
parent.findViewById<View>(sharedR.id.bc_smartspace_view)
?: parent.findViewById<View>(R.id.keyguard_slice_view)
if (targetSSView == null) {
- Log.e(TAG, "Failed to find smartspace equivalent target under $parent")
+ logger.e({ "Failed to find smartspace equivalent target under $str1" }) {
+ str1 = "$parent"
+ }
return
}
transition.values[SMARTSPACE_BOUNDS] = targetSSView.getRect()
@@ -143,10 +149,10 @@ class ClockSizeTransition(
endValues: TransitionValues?,
): Animator? {
if (startValues == null || endValues == null) {
- Log.w(
- TAG,
- "Couldn't create animator: startValues=$startValues; endValues=$endValues",
- )
+ logger.w({ "Couldn't create animator: startValues=$str1; endValues=$str2" }) {
+ str1 = "$startValues"
+ str2 = "$endValues"
+ }
return null
}
@@ -156,15 +162,18 @@ class ClockSizeTransition(
mutateTargets(from, to)
if (from.isVisible == to.isVisible && from.bounds.equals(to.bounds)) {
- if (DEBUG) {
- Log.w(
- TAG,
- "Skipping no-op transition: ${to.view}; " +
- "vis: ${from.visibility} -> ${to.visibility}; " +
- "alpha: ${from.alpha} -> ${to.alpha}; " +
- "bounds: ${from.bounds} -> ${to.bounds}; ",
- )
+ logger.w({
+ "Skipping no-op transition: $str1; " +
+ "vis: ${getVisText(int1)} -> ${getVisText(int2)}; " +
+ "alpha: $str2; bounds: $str3; "
+ }) {
+ str1 = "${to.view}"
+ int1 = from.visibility
+ int2 = to.visibility
+ str2 = "${from.alpha} -> ${to.alpha}"
+ str3 = "${from.bounds} -> ${to.bounds}"
}
+
return null
}
@@ -179,15 +188,27 @@ class ClockSizeTransition(
lerp(from.bounds.bottom, to.bounds.bottom, fract),
)
- fun assignAnimValues(src: String, fract: Float, vis: Int? = null) {
+ fun assignAnimValues(
+ src: String,
+ fract: Float,
+ vis: Int? = null,
+ log: Boolean = false,
+ ) {
mutateTargets(from, to)
val bounds = computeBounds(fract)
val alpha = MathUtils.lerp(from.alpha, to.alpha, fract)
- if (DEBUG) {
- Log.i(
- TAG,
- "$src: ${to.view}; fract=$fract; alpha=$alpha; vis=$vis; bounds=$bounds;",
- )
+ if (log) {
+ logger.i({
+ "$str1: $str2; fract=$int1%; alpha=$double1; " +
+ "vis=${getVisText(int2)}; bounds=$str3;"
+ }) {
+ str1 = src
+ str2 = "${to.view}"
+ int1 = (fract * 100).toInt()
+ double1 = alpha.toDouble()
+ int2 = vis ?: View.VISIBLE
+ str3 = "$bounds"
+ }
}
to.view.setVisibility(vis ?: View.VISIBLE)
@@ -195,14 +216,15 @@ class ClockSizeTransition(
to.view.setRect(bounds)
}
- if (DEBUG) {
- Log.i(
- TAG,
- "transitioning: ${to.view}; " +
- "vis: ${from.visibility} -> ${to.visibility}; " +
- "alpha: ${from.alpha} -> ${to.alpha}; " +
- "bounds: ${from.bounds} -> ${to.bounds}; ",
- )
+ logger.i({
+ "transitioning: $str1; vis: ${getVisText(int1)} -> ${getVisText(int2)}; " +
+ "alpha: $str2; bounds: $str3;"
+ }) {
+ str1 = "${to.view}"
+ int1 = from.visibility
+ int2 = to.visibility
+ str2 = "${from.alpha} -> ${to.alpha}"
+ str3 = "${from.bounds} -> ${to.bounds}"
}
return ValueAnimator.ofFloat(0f, 1f).also { anim ->
@@ -210,7 +232,7 @@ class ClockSizeTransition(
// predraw listener. This is suboptimal but prevents issues with layout passes
// overwriting the animation for individual frames.
val predrawCallback = OnPreDrawListener {
- assignAnimValues("predraw", anim.animatedFraction)
+ assignAnimValues("predraw", anim.animatedFraction, log = false)
return@OnPreDrawListener true
}
@@ -229,17 +251,17 @@ class ClockSizeTransition(
val listener =
object : AnimatorListenerAdapter() {
override fun onAnimationStart(anim: Animator) {
- assignAnimValues("start", 0f, from.visibility)
+ assignAnimValues("start", 0f, from.visibility, log = true)
}
override fun onAnimationEnd(anim: Animator) {
- assignAnimValues("end", 1f, to.visibility)
+ assignAnimValues("end", 1f, to.visibility, log = true)
if (sendToBack) to.view.translationZ = 0f
}
}
anim.addListener(listener)
- assignAnimValues("init", 0f, from.visibility)
+ assignAnimValues("init", 0f, from.visibility, log = true)
}
}
@@ -256,7 +278,8 @@ class ClockSizeTransition(
abstract class ClockFaceTransition(
config: IntraBlueprintTransition.Config,
val viewModel: KeyguardClockViewModel,
- ) : VisibilityBoundsTransition() {
+ logBuffer: LogBuffer,
+ ) : VisibilityBoundsTransition(logBuffer) {
protected abstract val isLargeClock: Boolean
protected abstract val smallClockMoveScale: Float
override val captureSmartspace
@@ -265,15 +288,17 @@ class ClockSizeTransition(
protected fun addTargets() {
if (isLargeClock) {
viewModel.currentClock.value?.let {
- if (DEBUG) Log.i(TAG, "Adding large clock views: ${it.largeClock.layout.views}")
+ logger.i({ "Adding large clock views: $str1" }) {
+ str1 = "${it.largeClock.layout.views}"
+ }
it.largeClock.layout.views.forEach { addTarget(it) }
}
?: run {
- Log.e(TAG, "No large clock set, falling back")
+ logger.e("No large clock set, falling back")
addTarget(customR.id.lockscreen_clock_view_large)
}
} else {
- if (DEBUG) Log.i(TAG, "Adding small clock")
+ logger.i("Adding small clock")
addTarget(customR.id.lockscreen_clock_view)
}
}
@@ -294,7 +319,7 @@ class ClockSizeTransition(
from.bounds.top = to.bounds.top - ssTranslation
from.bounds.bottom = to.bounds.bottom - ssTranslation
} else {
- Log.e(TAG, "initTargets: smallClock received no smartspace bounds")
+ logger.e("initTargets: smallClock received no smartspace bounds")
}
}
}
@@ -302,7 +327,8 @@ class ClockSizeTransition(
class ClockFaceInTransition(
config: IntraBlueprintTransition.Config,
viewModel: KeyguardClockViewModel,
- ) : ClockFaceTransition(config, viewModel) {
+ logBuffer: LogBuffer,
+ ) : ClockFaceTransition(config, viewModel, logBuffer) {
override val isLargeClock = viewModel.isLargeClockVisible.value
override val smallClockMoveScale = CLOCK_IN_MILLIS / STATUS_AREA_MOVE_DOWN_MILLIS.toFloat()
@@ -323,7 +349,8 @@ class ClockSizeTransition(
class ClockFaceOutTransition(
config: IntraBlueprintTransition.Config,
viewModel: KeyguardClockViewModel,
- ) : ClockFaceTransition(config, viewModel) {
+ logBuffer: LogBuffer,
+ ) : ClockFaceTransition(config, viewModel, logBuffer) {
override val isLargeClock = !viewModel.isLargeClockVisible.value
override val smallClockMoveScale = CLOCK_OUT_MILLIS / STATUS_AREA_MOVE_UP_MILLIS.toFloat()
@@ -342,7 +369,8 @@ class ClockSizeTransition(
class SmartspaceMoveTransition(
val config: IntraBlueprintTransition.Config,
val viewModel: KeyguardClockViewModel,
- ) : VisibilityBoundsTransition() {
+ logBuffer: LogBuffer,
+ ) : VisibilityBoundsTransition(logBuffer) {
private val isLargeClock = viewModel.isLargeClockVisible.value
override val captureSmartspace = false
@@ -361,7 +389,7 @@ class ClockSizeTransition(
override fun initTargets(from: Target, to: Target) {
// If view is changing visibility, hold it in place
if (from.isVisible == to.isVisible) return
- if (DEBUG) Log.i(TAG, "Holding position of ${to.view.id}")
+ logger.i({ "Holding position of $int1" }) { int1 = to.view.id }
if (from.isVisible) {
to.bounds.set(from.bounds)
@@ -383,8 +411,4 @@ class ClockSizeTransition(
const val STATUS_AREA_MOVE_DOWN_MILLIS = 467L
}
}
-
- companion object {
- val DEBUG = false
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
index 9f8e9c575a75..848bcabb7767 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
@@ -25,10 +25,8 @@ import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.statusbar.gesture.TapGestureDetector
import dagger.Lazy
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Provides dependencies for the AlternateBouncerViewBinder. */
-@ExperimentalCoroutinesApi
class AlternateBouncerDependencies
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt
index bbe5fedbf12f..06e6ee484e23 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt
@@ -26,7 +26,6 @@ import com.android.systemui.deviceentry.shared.model.FingerprintMessage
import com.android.systemui.statusbar.KeyguardIndicationController.DEFAULT_MESSAGE_TIME
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
@@ -38,7 +37,6 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
/** View model for the alternate bouncer message area. */
-@ExperimentalCoroutinesApi
class AlternateBouncerMessageAreaViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt
index 992550cdca5a..4558681a8f1f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModel.kt
@@ -26,7 +26,6 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
@@ -34,7 +33,6 @@ import kotlinx.coroutines.flow.flatMapLatest
* Breaks down ALTERNATE BOUNCER->AOD transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class AlternateBouncerToAodTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt
index 55a48b6bd49b..9a3cb7f27509 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToDozingTransitionViewModel.kt
@@ -25,7 +25,6 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
@@ -33,7 +32,6 @@ import kotlinx.coroutines.flow.flatMapLatest
* Breaks down ALTERNATE BOUNCER->DOZING transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class AlternateBouncerToDozingTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModel.kt
index e9db1d23ec3c..f42d74e153e0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModel.kt
@@ -29,14 +29,12 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.SysuiStatusBarStateController
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down ALTERNATE_BOUNCER->GONE transition into discrete steps for corresponding views to
* consume.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class AlternateBouncerToGoneTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt
index b04521cec881..c6ba441b11e5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToLockscreenTransitionViewModel.kt
@@ -26,14 +26,12 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down ALTERNATE_BOUNCER->LOCKSCREEN transition into discrete steps for corresponding views
* to consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class AlternateBouncerToLockscreenTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt
index c49e7833e349..c1ed7a02dbba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt
@@ -24,14 +24,12 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down ALTERNATE_BOUNCER->OCCLUDED transition into discrete steps for corresponding views to
* consume.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class AlternateBouncerToOccludedTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt
index b531c7fa49ec..43cce4b1c40c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt
@@ -30,7 +30,6 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
@@ -38,7 +37,6 @@ import kotlinx.coroutines.flow.emptyFlow
* Breaks down ALTERNATE BOUNCER->PRIMARY BOUNCER transition into discrete steps for corresponding
* views to consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class AlternateBouncerToPrimaryBouncerTransitionViewModel
@Inject
@@ -100,7 +98,11 @@ constructor(
override val windowBlurRadius: Flow<Float> =
shadeDependentFlows.transitionFlow(
flowWhenShadeIsExpanded =
- transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
+ if (Flags.notificationShadeBlur()) {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ } else {
+ emptyFlow()
+ },
flowWhenShadeIsNotExpanded =
transitionAnimation.sharedFlow(
duration = FromAlternateBouncerTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerUdfpsIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerUdfpsIconViewModel.kt
index 3a5263f3df77..acd381ec3280 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerUdfpsIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerUdfpsIconViewModel.kt
@@ -27,7 +27,6 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shared.recents.utilities.Utilities.clamp
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow
@@ -37,7 +36,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
/** Models the UI state for the UDFPS icon view in the alternate bouncer view. */
-@ExperimentalCoroutinesApi
class AlternateBouncerUdfpsIconViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
index b5d9e2ae888c..1ca08febd7ef 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
@@ -27,14 +27,12 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import dagger.Lazy
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
-@ExperimentalCoroutinesApi
class AlternateBouncerViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt
index 5cf100e78e6e..94f53b4dbb93 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerWindowViewModel.kt
@@ -20,14 +20,12 @@ import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
-@ExperimentalCoroutinesApi
class AlternateBouncerWindowViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
index fb311a533aa2..aed86648e3cf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.ui.viewmodel
import android.util.Log
@@ -37,7 +35,6 @@ import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlin.math.max
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
index 8e8b09d5cd67..4802abaab5c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToGoneTransitionViewModel.kt
@@ -27,11 +27,9 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/** Breaks down AOD->GONE transition into discrete steps for corresponding views to consume. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class AodToGoneTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
index 6eeab8db2a45..3c35566af6dd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
@@ -29,13 +29,11 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down AOD->LOCKSCREEN transition into discrete steps for corresponding views to consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class AodToLockscreenTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt
index 26bf0bc258e8..8b5e3b9756e3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt
@@ -28,7 +28,6 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
@@ -36,7 +35,6 @@ import kotlinx.coroutines.flow.emptyFlow
* Breaks down AOD->PRIMARY BOUNCER transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class AodToPrimaryBouncerTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
index 1edfec8f9e68..59cc15714e0e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
@@ -32,14 +32,12 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController
import dagger.Lazy
import javax.inject.Inject
import kotlin.time.Duration
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
/** ALTERNATE and PRIMARY bouncers common animations */
-@OptIn(ExperimentalCoroutinesApi::class)
class BouncerToGoneFlows
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
index 29ae4b94be6a..75bba489f893 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
@@ -25,7 +25,6 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -35,7 +34,6 @@ import kotlinx.coroutines.flow.onStart
/** Models the UI state for the device entry icon background view. */
@Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA")
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryBackgroundViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt
index 19652525bee0..5121b2ec822d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryForegroundViewModel.kt
@@ -30,7 +30,6 @@ import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlin.math.roundToInt
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.onStart
/** Models the UI state for the device entry icon foreground view (displayed icon). */
@OptIn(FlowPreview::class)
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryForegroundViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index b1a2ec92401a..84fdc6e3a433 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -38,7 +38,6 @@ import com.android.systemui.util.kotlin.sample
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -55,7 +54,6 @@ import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
/** Models the UI state for the containing device entry icon & long-press handling view. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryIconViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt
index 1e42e196bbc7..13a0e8e23ab4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt
@@ -17,12 +17,14 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
import com.android.systemui.keyguard.domain.interactor.FromDozingTransitionInteractor.Companion.TO_GLANCEABLE_HUB_DURATION
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -31,7 +33,10 @@ import kotlinx.coroutines.flow.flowOf
@SysUISingleton
class DozingToGlanceableHubTransitionViewModel
@Inject
-constructor(animationFlow: KeyguardTransitionAnimationFlow) : DeviceEntryIconTransition {
+constructor(
+ animationFlow: KeyguardTransitionAnimationFlow,
+ private val blurFactory: GlanceableHubBlurComponent.Factory,
+) : DeviceEntryIconTransition, GlanceableHubTransition {
private val transitionAnimation =
animationFlow
.setup(
@@ -48,4 +53,7 @@ constructor(animationFlow: KeyguardTransitionAnimationFlow) : DeviceEntryIconTra
* power button when dozing and docked.
*/
val notificationAlpha: Flow<Float> = flowOf(0f)
+
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().enterBlurRadius
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt
index 480f948f67f5..52ea419c7978 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGoneTransitionViewModel.kt
@@ -26,11 +26,9 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/** Breaks down DOZING->GONE transition into discrete steps for corresponding views to consume. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class DozingToGoneTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt
index 9d8a7a81b9dc..672ed52af267 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToLockscreenTransitionViewModel.kt
@@ -25,13 +25,11 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down DOZING->LOCKSCREEN transition into discrete steps for corresponding views to consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class DozingToLockscreenTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt
index d9ca267f9445..ff96e035bc81 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt
@@ -28,7 +28,6 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
@@ -36,7 +35,6 @@ import kotlinx.coroutines.flow.emptyFlow
* Breaks down DOZING->PRIMARY BOUNCER transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class DozingToPrimaryBouncerTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt
index 75623924497e..7c26e0bcd76f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToAodTransitionViewModel.kt
@@ -26,13 +26,11 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
/** Breaks down DREAMING->AOD transition into discrete steps for corresponding views to consume. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class DreamingToAodTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
index c9fdf7a31458..4e07ca0da27e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
@@ -20,30 +20,31 @@ import android.util.LayoutDirection
import com.android.app.animation.Interpolators.EMPHASIZED
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class DreamingToGlanceableHubTransitionViewModel
@Inject
constructor(
animationFlow: KeyguardTransitionAnimationFlow,
@ShadeDisplayAware configurationInteractor: ConfigurationInteractor,
-) : DeviceEntryIconTransition {
+ private val blurFactory: GlanceableHubBlurComponent.Factory,
+) : DeviceEntryIconTransition, GlanceableHubTransition {
private val transitionAnimation =
animationFlow
.setup(
@@ -101,4 +102,7 @@ constructor(
private companion object {
val TO_GLANCEABLE_HUB_DURATION = 1.seconds
}
+
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().enterBlurRadius
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index 10605b28a862..5dd6d2e049d7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -26,14 +26,12 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down DREAMING->LOCKSCREEN transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class DreamingToLockscreenTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModel.kt
new file mode 100644
index 000000000000..6738b277766a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModel.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
+import com.android.systemui.keyguard.domain.interactor.FromDozingTransitionInteractor.Companion.TO_GLANCEABLE_HUB_DURATION
+import com.android.systemui.keyguard.shared.model.Edge
+import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
+import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
+import com.android.systemui.scene.shared.model.Scenes
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+@SysUISingleton
+class GlanceableHubToDozingTransitionViewModel
+@Inject
+constructor(
+ animationFlow: KeyguardTransitionAnimationFlow,
+ private val blurComponentFactory: GlanceableHubBlurComponent.Factory,
+) : GlanceableHubTransition {
+ private val transitionAnimation =
+ animationFlow
+ .setup(
+ duration = TO_GLANCEABLE_HUB_DURATION,
+ edge = Edge.create(DOZING, Scenes.Communal),
+ )
+ .setupWithoutSceneContainer(edge = Edge.create(GLANCEABLE_HUB, DOZING))
+
+ override val windowBlurRadius: Flow<Float> =
+ blurComponentFactory.create(transitionAnimation).getBlurProvider().exitBlurRadius
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt
index 723fba6d976e..2b8ca8a68611 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModel.kt
@@ -20,30 +20,31 @@ import android.util.LayoutDirection
import com.android.app.animation.Interpolators
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class GlanceableHubToDreamingTransitionViewModel
@Inject
constructor(
animationFlow: KeyguardTransitionAnimationFlow,
@ShadeDisplayAware configurationInteractor: ConfigurationInteractor,
-) : DeviceEntryIconTransition {
+ private val blurFactory: GlanceableHubBlurComponent.Factory,
+) : DeviceEntryIconTransition, GlanceableHubTransition {
private val transitionAnimation =
animationFlow
@@ -96,6 +97,9 @@ constructor(
onFinish = { 0f },
)
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().exitBlurRadius
+
private companion object {
val FROM_GLANCEABLE_HUB_DURATION = 1.seconds
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt
index 5a4d0689d209..b4b4c82c59b9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt
@@ -20,18 +20,19 @@ import android.util.LayoutDirection
import com.android.app.animation.Interpolators.EMPHASIZED
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
import com.android.systemui.keyguard.domain.interactor.FromGlanceableHubTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.StateToValue
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
@@ -41,14 +42,14 @@ import kotlinx.coroutines.flow.map
* Breaks down GLANCEABLE_HUB->LOCKSCREEN transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class GlanceableHubToLockscreenTransitionViewModel
@Inject
constructor(
@ShadeDisplayAware configurationInteractor: ConfigurationInteractor,
animationFlow: KeyguardTransitionAnimationFlow,
-) {
+ private val blurFactory: GlanceableHubBlurComponent.Factory,
+) : GlanceableHubTransition {
private val transitionAnimation =
animationFlow
.setup(
@@ -57,6 +58,9 @@ constructor(
)
.setupWithoutSceneContainer(edge = Edge.create(from = GLANCEABLE_HUB, to = LOCKSCREEN))
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().exitBlurRadius
+
val keyguardAlpha: Flow<Float> =
transitionAnimation.sharedFlow(
duration = 167.milliseconds,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModel.kt
index cd98bb00b9dc..c3a412a5d49b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModel.kt
@@ -17,12 +17,14 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
import com.android.systemui.keyguard.domain.interactor.FromGlanceableHubTransitionInteractor.Companion.TO_OCCLUDED_DURATION
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -32,7 +34,8 @@ class GlanceableHubToOccludedTransitionViewModel
@Inject
constructor(
animationFlow: KeyguardTransitionAnimationFlow,
-) : DeviceEntryIconTransition {
+ private val blurFactory: GlanceableHubBlurComponent.Factory,
+) : DeviceEntryIconTransition, GlanceableHubTransition {
private val transitionAnimation =
animationFlow
@@ -44,4 +47,7 @@ constructor(
override val deviceEntryParentViewAlpha: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(0f)
+
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().exitBlurRadius
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt
index 5ab458334a25..40010548a268 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt
@@ -16,6 +16,9 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.Flags
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
+import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
@@ -26,12 +29,17 @@ import com.android.systemui.keyguard.ui.transitions.BlurConfig
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.flatMapLatest
@SysUISingleton
class GlanceableHubToPrimaryBouncerTransitionViewModel
@Inject
-constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFlow) :
- PrimaryBouncerTransition {
+constructor(
+ private val blurConfig: BlurConfig,
+ animationFlow: KeyguardTransitionAnimationFlow,
+ communalSettingsInteractor: CommunalSettingsInteractor,
+) : PrimaryBouncerTransition {
private val transitionAnimation =
animationFlow
.setup(
@@ -41,7 +49,15 @@ constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitio
.setupWithoutSceneContainer(edge = Edge.create(GLANCEABLE_HUB, PRIMARY_BOUNCER))
override val windowBlurRadius: Flow<Float> =
- transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ if (Flags.glanceableHubBlurredBackground()) {
+ communalSettingsInteractor.communalBackground
+ .filter { it != CommunalBackgroundType.BLUR }
+ .flatMapLatest {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ }
+ } else {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ }
override val notificationBlurRadius: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(0.0f)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
index 43872b705ae0..bedcf142f528 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
@@ -32,14 +32,12 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.transform
/** Breaks down GONE->AOD transition into discrete steps for corresponding views to consume. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class GoneToAodTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt
index c62e4f4ba243..45c3daac16d5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDozingTransitionViewModel.kt
@@ -27,13 +27,11 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
/** Breaks down GONE->DOZING transition into discrete steps for corresponding views to consume. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class GoneToDozingTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
index 1289036c7ae0..d7be356f99e3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt
@@ -20,7 +20,6 @@ package com.android.systemui.keyguard.ui.viewmodel
import android.os.Handler
import android.transition.Transition
import android.transition.TransitionManager
-import android.util.Log
import androidx.constraintlayout.widget.ConstraintLayout
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
@@ -29,6 +28,9 @@ import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.KeyguardBlueprintLog
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -41,7 +43,9 @@ constructor(
@Main private val handler: Handler,
private val keyguardBlueprintInteractor: KeyguardBlueprintInteractor,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ @KeyguardBlueprintLog private val blueprintLog: LogBuffer,
) {
+ private val logger = Logger(blueprintLog, "KeyguardBlueprintViewModel")
val blueprint = keyguardBlueprintInteractor.blueprint
val blueprintId = keyguardBlueprintInteractor.blueprintId
val refreshTransition = keyguardBlueprintInteractor.refreshTransition
@@ -53,27 +57,27 @@ constructor(
private val transitionListener =
object : Transition.TransitionListener {
override fun onTransitionCancel(transition: Transition) {
- if (DEBUG) Log.w(TAG, "onTransitionCancel: ${transition::class.simpleName}")
+ logger.w({ "onTransitionCancel: $str1" }) { str1 = transition::class.simpleName }
updateTransitions(null) { remove(transition) }
}
override fun onTransitionEnd(transition: Transition) {
- if (DEBUG) Log.i(TAG, "onTransitionEnd: ${transition::class.simpleName}")
+ logger.i({ "onTransitionEnd: $str1" }) { str1 = transition::class.simpleName }
updateTransitions(null) { remove(transition) }
}
override fun onTransitionPause(transition: Transition) {
- if (DEBUG) Log.i(TAG, "onTransitionPause: ${transition::class.simpleName}")
+ logger.i({ "onTransitionPause: $str1" }) { str1 = transition::class.simpleName }
updateTransitions(null) { remove(transition) }
}
override fun onTransitionResume(transition: Transition) {
- if (DEBUG) Log.i(TAG, "onTransitionResume: ${transition::class.simpleName}")
+ logger.i({ "onTransitionResume: $str1" }) { str1 = transition::class.simpleName }
updateTransitions(null) { add(transition) }
}
override fun onTransitionStart(transition: Transition) {
- if (DEBUG) Log.i(TAG, "onTransitionStart: ${transition::class.simpleName}")
+ logger.i({ "onTransitionStart: $str1" }) { str1 = transition::class.simpleName }
updateTransitions(null) { add(transition) }
}
}
@@ -104,7 +108,7 @@ constructor(
runTransition(
constraintLayout,
- IntraBlueprintTransition(newConfig, clockViewModel, smartspaceViewModel),
+ IntraBlueprintTransition(newConfig, clockViewModel, smartspaceViewModel, blueprintLog),
config,
apply,
)
@@ -118,12 +122,10 @@ constructor(
) {
val currentPriority = currentTransition.value?.let { it.config.type.priority } ?: -1
if (config.checkPriority && config.type.priority < currentPriority) {
- if (DEBUG) {
- Log.w(
- TAG,
- "runTransition: skipping ${transition::class.simpleName}: " +
- "currentPriority=$currentPriority; config=$config",
- )
+ logger.w({ "runTransition: skipping $str1: currentPriority=$int1; config=$str2" }) {
+ str1 = transition::class.simpleName
+ int1 = currentPriority
+ str2 = "$config"
}
apply()
return
@@ -137,12 +139,10 @@ constructor(
config
}
- if (DEBUG) {
- Log.i(
- TAG,
- "runTransition: running ${transition::class.simpleName}: " +
- "currentPriority=$currentPriority; config=$newConfig",
- )
+ logger.i({ "runTransition: running $str1: currentPriority=$int1; config=$str2" }) {
+ str1 = transition::class.simpleName
+ int1 = currentPriority
+ str2 = "$newConfig"
}
// beginDelayedTransition makes a copy, so we temporarially add the uncopied transition to
@@ -162,9 +162,4 @@ constructor(
handler.post { updateTransitions(null) { remove(transition) } }
}
}
-
- companion object {
- private const val TAG = "KeyguardBlueprintViewModel"
- private const val DEBUG = false
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
index 3dcc60a98506..8849d24fdee6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
@@ -33,7 +33,6 @@ import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -75,7 +74,6 @@ constructor(
}
.distinctUntilChanged()
- @OptIn(ExperimentalCoroutinesApi::class)
private val burnIn: Flow<BurnInModel> =
combine(
burnInInteractor.burnIn(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
index df3c78232b94..7a9e55ac1109 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
@@ -34,7 +34,6 @@ import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordance
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -45,7 +44,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
class KeyguardQuickAffordancesCombinedViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index aa4293a201ac..f0c924f99033 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -57,7 +57,6 @@ import com.android.systemui.util.ui.zip
import javax.inject.Inject
import kotlin.math.max
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -70,7 +69,6 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardRootViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSettingsMenuViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSettingsMenuViewModel.kt
index 36a342b13df7..4584ea24b0f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSettingsMenuViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSettingsMenuViewModel.kt
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.Text
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTouchHandlingInteractor
import com.android.systemui.res.R
import javax.inject.Inject
@@ -29,19 +30,18 @@ class KeyguardSettingsMenuViewModel
@Inject
constructor(
private val interactor: KeyguardTouchHandlingInteractor,
+ configurationInteractor: ConfigurationInteractor,
) {
val isVisible: Flow<Boolean> = interactor.isMenuVisible
val shouldOpenSettings: Flow<Boolean> = interactor.shouldOpenSettings
- val icon: Icon =
- Icon.Resource(
- res = R.drawable.ic_palette,
- contentDescription = null,
- )
+ val icon: Icon = Icon.Resource(res = R.drawable.ic_palette, contentDescription = null)
+
+ val text: Text = Text.Resource(res = R.string.lock_screen_settings)
- val text: Text =
- Text.Resource(
- res = R.string.lock_screen_settings,
+ val textSize =
+ configurationInteractor.dimensionPixelSize(
+ com.android.internal.R.dimen.text_size_small_material
)
fun onTouchGestureStarted() {
@@ -49,9 +49,7 @@ constructor(
}
fun onTouchGestureEnded(isClick: Boolean) {
- interactor.onMenuTouchGestureEnded(
- isClick = isClick,
- )
+ interactor.onMenuTouchGestureEnded(isClick = isClick)
}
fun onSettingsShown() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
index 6d1aefe813c3..16e32df24bd3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
@@ -19,7 +19,6 @@ package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.keyguard.domain.interactor.LightRevealScrimInteractor
import com.android.systemui.statusbar.LightRevealEffect
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
@@ -27,7 +26,6 @@ import kotlinx.coroutines.flow.map
* Models UI state for the light reveal scrim, which is used during screen on and off animations to
* draw a gradient that reveals/hides the contents of the screen.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
class LightRevealScrimViewModel
@Inject
constructor(private val interactor: LightRevealScrimInteractor) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
index 2f21ebc6eb42..6b4f4c1a3c91 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
@@ -32,7 +32,6 @@ import com.android.systemui.power.shared.model.WakeSleepReason.FOLD
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.transform
@@ -40,7 +39,6 @@ import kotlinx.coroutines.flow.transform
/**
* Breaks down LOCKSCREEN->AOD transition into discrete steps for corresponding views to consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class LockscreenToAodTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
index 7abf35de5dae..dc7fefa1d754 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
@@ -26,11 +26,9 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class LockscreenToDozingTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt
index acaa9b918da8..d4cad710ec79 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt
@@ -20,18 +20,19 @@ import android.util.LayoutDirection
import com.android.app.animation.Interpolators.EMPHASIZED
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.StateToValue
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
@@ -41,14 +42,15 @@ import kotlinx.coroutines.flow.map
* Breaks down LOCKSCREEN->GLANCEABLE_HUB transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class LockscreenToGlanceableHubTransitionViewModel
@Inject
constructor(
@ShadeDisplayAware configurationInteractor: ConfigurationInteractor,
animationFlow: KeyguardTransitionAnimationFlow,
-) {
+ private val blurFactory: GlanceableHubBlurComponent.Factory,
+) : GlanceableHubTransition {
+
private val transitionAnimation =
animationFlow
.setup(
@@ -57,6 +59,9 @@ constructor(
)
.setupWithoutSceneContainer(edge = Edge.create(from = LOCKSCREEN, to = GLANCEABLE_HUB))
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().enterBlurRadius
+
val keyguardAlpha: Flow<Float> =
transitionAnimation.sharedFlow(
duration = 167.milliseconds,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt
index a249793798ed..a31bc7572fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModel.kt
@@ -30,13 +30,11 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.SysuiStatusBarStateController
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down LOCKSCREEN->GONE transition into discrete steps for corresponding views to consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class LockscreenToGoneTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
index 89dcbf6aa52b..b96c879157dc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
@@ -31,7 +31,6 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
@@ -39,7 +38,6 @@ import kotlinx.coroutines.flow.emptyFlow
* Breaks down LOCKSCREEN->PRIMARY BOUNCER transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class LockscreenToPrimaryBouncerTransitionViewModel
@Inject
@@ -107,7 +105,11 @@ constructor(
override val windowBlurRadius: Flow<Float> =
shadeDependentFlows.transitionFlow(
flowWhenShadeIsExpanded =
- transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
+ if (Flags.notificationShadeBlur()) {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ } else {
+ emptyFlow()
+ },
flowWhenShadeIsNotExpanded =
transitionAnimation.sharedFlow(
duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
index 618b04700afb..b7e3e2b38732 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.ui.viewmodel
import com.android.compose.animation.scene.Swipe
@@ -33,7 +31,6 @@ import com.android.systemui.shade.ui.viewmodel.singleShadeActions
import com.android.systemui.shade.ui.viewmodel.splitShadeActions
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAlternateBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAlternateBouncerTransitionViewModel.kt
index 5bfcccbaccaa..092031b809c2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAlternateBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAlternateBouncerTransitionViewModel.kt
@@ -24,14 +24,12 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
* Breaks down OCCLUDED->ALTERNATE_BOUNCER transition into discrete steps for corresponding views to
* consume.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class OccludedToAlternateBouncerTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt
index 706a3c440723..a8376edeaaeb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToAodTransitionViewModel.kt
@@ -26,13 +26,11 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
/** Breaks down OCCLUDED->AOD transition into discrete steps for corresponding views to consume. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class OccludedToAodTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToDozingTransitionViewModel.kt
index 4fb2b9b35e88..1ead9c1d2647 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToDozingTransitionViewModel.kt
@@ -26,7 +26,6 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
@@ -34,7 +33,6 @@ import kotlinx.coroutines.flow.flatMapLatest
/**
* Breaks down OCCLUDED->DOZING transition into discrete steps for corresponding views to consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class OccludedToDozingTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModel.kt
index 47e202b8fcc3..e74607d5a4b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModel.kt
@@ -17,12 +17,14 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_GLANCEABLE_HUB_DURATION
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -32,16 +34,20 @@ class OccludedToGlanceableHubTransitionViewModel
@Inject
constructor(
animationFlow: KeyguardTransitionAnimationFlow,
-) : DeviceEntryIconTransition {
+ private val blurFactory: GlanceableHubBlurComponent.Factory,
+) : DeviceEntryIconTransition, GlanceableHubTransition {
private val transitionAnimation =
animationFlow
.setup(
duration = TO_GLANCEABLE_HUB_DURATION,
- edge = Edge.create(OCCLUDED, Scenes.Communal)
+ edge = Edge.create(OCCLUDED, Scenes.Communal),
)
.setupWithoutSceneContainer(edge = Edge.create(OCCLUDED, GLANCEABLE_HUB))
override val deviceEntryParentViewAlpha: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(1f)
+
+ override val windowBlurRadius: Flow<Float> =
+ blurFactory.create(transitionAnimation).getBlurProvider().enterBlurRadius
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt
index 98dba393a545..88d663808641 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGoneTransitionViewModel.kt
@@ -24,11 +24,9 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/** Breaks down OCCLUDED->GONE transition into discrete steps for corresponding views to consume. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class OccludedToGoneTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
index d10970f28995..6b9d4cf00050 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
@@ -33,7 +33,6 @@ import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
@@ -44,7 +43,6 @@ import kotlinx.coroutines.flow.merge
* Breaks down OCCLUDED->LOCKSCREEN transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class OccludedToLockscreenTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModel.kt
index 4d3e27265cea..3c126aa23fef 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
@@ -26,12 +27,16 @@ import com.android.systemui.keyguard.ui.transitions.BlurConfig
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
@SysUISingleton
class OccludedToPrimaryBouncerTransitionViewModel
@Inject
-constructor(blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFlow) :
- PrimaryBouncerTransition {
+constructor(
+ shadeDependentFlows: ShadeDependentFlows,
+ blurConfig: BlurConfig,
+ animationFlow: KeyguardTransitionAnimationFlow,
+) : PrimaryBouncerTransition {
private val transitionAnimation =
animationFlow
.setup(
@@ -41,8 +46,21 @@ constructor(blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFl
.setupWithoutSceneContainer(edge = Edge.create(OCCLUDED, PRIMARY_BOUNCER))
override val windowBlurRadius: Flow<Float> =
- transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ shadeDependentFlows.transitionFlow(
+ flowWhenShadeIsExpanded =
+ if (Flags.notificationShadeBlur()) {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ } else {
+ emptyFlow()
+ },
+ flowWhenShadeIsNotExpanded =
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
+ )
override val notificationBlurRadius: Flow<Float> =
- transitionAnimation.immediatelyTransitionTo(0.0f)
+ shadeDependentFlows.transitionFlow(
+ flowWhenShadeIsExpanded =
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
+ flowWhenShadeIsNotExpanded = emptyFlow(),
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludingAppDeviceEntryMessageViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludingAppDeviceEntryMessageViewModel.kt
index 846bcbfd38d9..d32b3b424683 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludingAppDeviceEntryMessageViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludingAppDeviceEntryMessageViewModel.kt
@@ -21,11 +21,9 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.OccludingAppDeviceEntryInteractor
import com.android.systemui.deviceentry.shared.model.BiometricMessage
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/** Shows authentication messages over occcluding apps over the lockscreen. */
-@ExperimentalCoroutinesApi
@SysUISingleton
class OccludingAppDeviceEntryMessageViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
index 224191b64f5f..dc75829f95ee 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
@@ -29,7 +29,6 @@ import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
@@ -38,7 +37,6 @@ import kotlinx.coroutines.flow.flatMapLatest
* Breaks down PRIMARY BOUNCER->AOD transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class PrimaryBouncerToAodTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt
index 0f8495f34d22..7f431bc3e0f9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt
@@ -28,7 +28,6 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
@@ -37,7 +36,6 @@ import kotlinx.coroutines.flow.flatMapLatest
* Breaks down PRIMARY BOUNCER->DOZING transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class PrimaryBouncerToDozingTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt
index a13eef2388f7..89c0ba144196 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt
@@ -16,6 +16,9 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.Flags
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
+import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GLANCEABLE_HUB_DURATION
import com.android.systemui.keyguard.shared.model.Edge
@@ -27,12 +30,17 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.flatMapLatest
@SysUISingleton
class PrimaryBouncerToGlanceableHubTransitionViewModel
@Inject
-constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFlow) :
- DeviceEntryIconTransition, PrimaryBouncerTransition {
+constructor(
+ blurConfig: BlurConfig,
+ animationFlow: KeyguardTransitionAnimationFlow,
+ communalSettingsInteractor: CommunalSettingsInteractor,
+) : DeviceEntryIconTransition, PrimaryBouncerTransition {
private val transitionAnimation =
animationFlow
.setup(duration = TO_GLANCEABLE_HUB_DURATION, edge = Edge.INVALID)
@@ -42,7 +50,15 @@ constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitio
transitionAnimation.immediatelyTransitionTo(1f)
override val windowBlurRadius: Flow<Float> =
- transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx)
+ if (Flags.glanceableHubBlurredBackground()) {
+ communalSettingsInteractor.communalBackground
+ .filter { it != CommunalBackgroundType.BLUR }
+ .flatMapLatest {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx)
+ }
+ } else {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx)
+ }
override val notificationBlurRadius: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(0.0f)
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
index d1233f220f47..34c87feb0a0d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -33,7 +33,6 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController
import dagger.Lazy
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
@@ -41,7 +40,6 @@ import kotlinx.coroutines.flow.flatMapLatest
* Breaks down PRIMARY_BOUNCER->GONE transition into discrete steps for corresponding views to
* consume.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class PrimaryBouncerToGoneTransitionViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
index c53a408a88e1..9cb03874e412 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.viewmodel
import android.util.MathUtils
import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
@@ -30,14 +31,13 @@ import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
/**
* Breaks down PRIMARY BOUNCER->LOCKSCREEN transition into discrete steps for corresponding views to
* consume.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class PrimaryBouncerToLockscreenTransitionViewModel
@Inject
@@ -78,7 +78,11 @@ constructor(
override val windowBlurRadius: Flow<Float> =
shadeDependentFlows.transitionFlow(
flowWhenShadeIsExpanded =
- transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
+ if (Flags.notificationShadeBlur()) {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ } else {
+ emptyFlow()
+ },
flowWhenShadeIsNotExpanded =
transitionAnimation.sharedFlow(
duration = FromPrimaryBouncerTransitionInteractor.TO_LOCKSCREEN_DURATION,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModel.kt
index fe1708efea2f..0f0e7b6faa66 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
@@ -26,12 +27,16 @@ import com.android.systemui.keyguard.ui.transitions.BlurConfig
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
@SysUISingleton
class PrimaryBouncerToOccludedTransitionViewModel
@Inject
-constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFlow) :
- PrimaryBouncerTransition {
+constructor(
+ shadeDependentFlows: ShadeDependentFlows,
+ blurConfig: BlurConfig,
+ animationFlow: KeyguardTransitionAnimationFlow,
+) : PrimaryBouncerTransition {
private val transitionAnimation =
animationFlow
.setup(
@@ -41,7 +46,16 @@ constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitio
.setupWithoutSceneContainer(edge = Edge.create(PRIMARY_BOUNCER, OCCLUDED))
override val windowBlurRadius: Flow<Float> =
- transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx)
+ shadeDependentFlows.transitionFlow(
+ flowWhenShadeIsExpanded =
+ if (Flags.notificationShadeBlur()) {
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
+ } else {
+ emptyFlow()
+ },
+ flowWhenShadeIsNotExpanded =
+ transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx),
+ )
override val notificationBlurRadius: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(0.0f)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
index 3de1f1e6258e..106ecc6cdfa8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
@@ -45,7 +45,6 @@ import com.android.systemui.statusbar.phone.DozeServiceHost
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -62,7 +61,6 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onCompletion
import com.android.app.tracing.coroutines.launchTraced as launch
-@ExperimentalCoroutinesApi
@SysUISingleton
class SideFpsProgressBarViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt
index 8732ef576335..50979682f553 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt
@@ -24,6 +24,12 @@ import javax.inject.Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class KeyguardClockLog
+/** A [com.android.systemui.log.LogBuffer] for keyguard blueprint logs. */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class KeyguardBlueprintLog
+
/** A [com.android.systemui.log.LogBuffer] for small keyguard clock logs. */
@Qualifier
@MustBeDocumented
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 8097d9585fb5..faa6c52162ce 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -321,6 +321,16 @@ public class LogModule {
}
/**
+ * Provides a {@link LogBuffer} for keyguard blueprint logs.
+ */
+ @Provides
+ @SysUISingleton
+ @KeyguardBlueprintLog
+ public static LogBuffer provideKeyguardBlueprintLog(LogBufferFactory factory) {
+ return factory.create("KeyguardBlueprintLog", 100);
+ }
+
+ /**
* Provides a {@link LogBuffer} for general keyguard clock logs.
*/
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/log/echo/LogcatEchoTrackerDebug.kt b/packages/SystemUI/src/com/android/systemui/log/echo/LogcatEchoTrackerDebug.kt
index 21808b691cd0..704c990fcb98 100644
--- a/packages/SystemUI/src/com/android/systemui/log/echo/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/echo/LogcatEchoTrackerDebug.kt
@@ -26,7 +26,6 @@ import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import com.android.app.tracing.coroutines.launchTraced as launch
/**
@@ -39,7 +38,6 @@ import com.android.app.tracing.coroutines.launchTraced as launch
* Note that some log messages may fail to be echoed while the systemui process is first starting
* up, before we load the echo settings.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
class LogcatEchoTrackerDebug
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
index baa07c14ae04..9fddbfb16d4d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
@@ -65,7 +65,7 @@ interface Diffable<T> {
*/
fun <T : Diffable<T>> Flow<T>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
initialValue: T,
): Flow<T> {
// Fully log the initial value to the table.
@@ -87,7 +87,7 @@ fun <T : Diffable<T>> Flow<T>.logDiffsForTable(
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<Boolean>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: Boolean,
): Flow<Boolean> {
@@ -106,7 +106,7 @@ fun Flow<Boolean>.logDiffsForTable(
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<Int>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: Int,
): Flow<Int> {
@@ -125,7 +125,7 @@ fun Flow<Int>.logDiffsForTable(
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<Int?>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: Int?,
): Flow<Int?> {
@@ -144,7 +144,7 @@ fun Flow<Int?>.logDiffsForTable(
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<String?>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: String?,
): Flow<String?> {
@@ -163,7 +163,7 @@ fun Flow<String?>.logDiffsForTable(
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun <T> Flow<List<T>>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: List<T>,
): Flow<List<T>> {
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 89a599a77b40..3d1623b2d5b6 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -124,7 +124,7 @@ class TableLogBuffer(
* 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) {
+ fun <T : Diffable<T>> logDiffs(columnPrefix: String = "", prevVal: T, newVal: T) {
val row = tempRow
row.timestamp = systemClock.currentTimeMillis()
row.columnPrefix = columnPrefix
@@ -136,6 +136,7 @@ class TableLogBuffer(
/**
* Logs change(s) to the buffer using [rowInitializer].
*
+ * @param columnPrefix see [logDiffs].
* @param rowInitializer a function that will be called immediately to store relevant data on
* the row.
* @param isInitial true if this change represents the starting value for a particular column
@@ -145,9 +146,9 @@ class TableLogBuffer(
*/
@Synchronized
fun logChange(
- columnPrefix: String,
+ columnPrefix: String = "",
isInitial: Boolean = false,
- rowInitializer: (TableRowLogger) -> Unit
+ rowInitializer: (TableRowLogger) -> Unit,
) {
val row = tempRow
row.timestamp = systemClock.currentTimeMillis()
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt
new file mode 100644
index 000000000000..ece97bd27df7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/AmbientLightModeMonitor.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock
+
+import android.annotation.IntDef
+import android.hardware.Sensor
+import android.hardware.SensorEvent
+import android.hardware.SensorEventListener
+import android.hardware.SensorManager
+import android.util.Log
+import com.android.systemui.Dumpable
+import com.android.systemui.lowlightclock.dagger.LowLightModule.LIGHT_SENSOR
+import com.android.systemui.util.sensors.AsyncSensorManager
+import java.io.PrintWriter
+import java.util.Optional
+import javax.inject.Inject
+import javax.inject.Named
+
+/**
+ * Monitors ambient light signals, applies a debouncing algorithm, and produces the current ambient
+ * light mode.
+ *
+ * @property algorithm the debounce algorithm which transforms light sensor events into an ambient
+ * light mode.
+ * @property sensorManager the sensor manager used to register sensor event updates.
+ */
+class AmbientLightModeMonitor
+@Inject
+constructor(
+ private val algorithm: Optional<DebounceAlgorithm>,
+ private val sensorManager: AsyncSensorManager,
+ @Named(LIGHT_SENSOR) private val lightSensor: Optional<Sensor>,
+) : Dumpable {
+ companion object {
+ private const val TAG = "AmbientLightModeMonitor"
+ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
+
+ const val AMBIENT_LIGHT_MODE_LIGHT = 0
+ const val AMBIENT_LIGHT_MODE_DARK = 1
+ const val AMBIENT_LIGHT_MODE_UNDECIDED = 2
+ }
+
+ // Represents all ambient light modes.
+ @Retention(AnnotationRetention.SOURCE)
+ @IntDef(AMBIENT_LIGHT_MODE_LIGHT, AMBIENT_LIGHT_MODE_DARK, AMBIENT_LIGHT_MODE_UNDECIDED)
+ annotation class AmbientLightMode
+
+ /**
+ * Start monitoring the current ambient light mode.
+ *
+ * @param callback callback that gets triggered when the ambient light mode changes.
+ */
+ fun start(callback: Callback) {
+ if (DEBUG) Log.d(TAG, "start monitoring ambient light mode")
+
+ if (lightSensor.isEmpty) {
+ if (DEBUG) Log.w(TAG, "light sensor not available")
+ return
+ }
+
+ if (algorithm.isEmpty) {
+ if (DEBUG) Log.w(TAG, "debounce algorithm not available")
+ return
+ }
+
+ algorithm.get().start(callback)
+ sensorManager.registerListener(
+ mSensorEventListener,
+ lightSensor.get(),
+ SensorManager.SENSOR_DELAY_NORMAL,
+ )
+ }
+
+ /** Stop monitoring the current ambient light mode. */
+ fun stop() {
+ if (DEBUG) Log.d(TAG, "stop monitoring ambient light mode")
+
+ if (algorithm.isPresent) {
+ algorithm.get().stop()
+ }
+ sensorManager.unregisterListener(mSensorEventListener)
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println()
+ pw.println("Ambient light mode monitor:")
+ pw.println(" lightSensor=$lightSensor")
+ pw.println()
+ }
+
+ private val mSensorEventListener: SensorEventListener =
+ object : SensorEventListener {
+ override fun onSensorChanged(event: SensorEvent) {
+ if (event.values.isEmpty()) {
+ if (DEBUG) Log.w(TAG, "SensorEvent doesn't have any value")
+ return
+ }
+
+ if (algorithm.isPresent) {
+ algorithm.get().onUpdateLightSensorEvent(event.values[0])
+ }
+ }
+
+ override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
+ // Do nothing.
+ }
+ }
+
+ /** Interface of the ambient light mode callback, which gets triggered when the mode changes. */
+ interface Callback {
+ fun onChange(@AmbientLightMode mode: Int)
+ }
+
+ /** Interface of the algorithm that transforms light sensor events to an ambient light mode. */
+ interface DebounceAlgorithm {
+ // Setting Callback to nullable so mockito can verify without throwing NullPointerException.
+ fun start(callback: Callback?)
+
+ fun stop()
+
+ fun onUpdateLightSensorEvent(value: Float)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/ChargingStatusProvider.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/ChargingStatusProvider.java
new file mode 100644
index 000000000000..8cc399b0a22b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/ChargingStatusProvider.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.BatteryManager;
+import android.os.RemoteException;
+import android.text.format.Formatter;
+import android.util.Log;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.Preconditions;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.settingslib.fuelgauge.BatteryStatus;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
+
+import java.text.NumberFormat;
+
+import javax.inject.Inject;
+
+/**
+ * Provides charging status as a string to a registered callback such that it can be displayed to
+ * the user (e.g. on the low-light clock).
+ * TODO(b/223681352): Make this code shareable with {@link KeyguardIndicationController}.
+ */
+public class ChargingStatusProvider {
+ private static final String TAG = "ChargingStatusProvider";
+
+ private final Resources mResources;
+ private final Context mContext;
+ private final IBatteryStats mBatteryInfo;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final BatteryState mBatteryState = new BatteryState();
+ // This callback is registered with KeyguardUpdateMonitor, which only keeps weak references to
+ // its callbacks. Therefore, an explicit reference needs to be kept here to avoid the
+ // callback being GC'd.
+ private ChargingStatusCallback mChargingStatusCallback;
+
+ private Callback mCallback;
+
+ @Inject
+ public ChargingStatusProvider(
+ Context context,
+ @Main Resources resources,
+ IBatteryStats iBatteryStats,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ mContext = context;
+ mResources = resources;
+ mBatteryInfo = iBatteryStats;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ }
+
+ /**
+ * Start using the {@link ChargingStatusProvider}.
+ * @param callback A callback to be called when the charging status changes.
+ */
+ public void startUsing(Callback callback) {
+ Preconditions.checkState(
+ mCallback == null, "ChargingStatusProvider already started!");
+ mCallback = callback;
+ mChargingStatusCallback = new ChargingStatusCallback();
+ mKeyguardUpdateMonitor.registerCallback(mChargingStatusCallback);
+ reportStatusToCallback();
+ }
+
+ /**
+ * Stop using the {@link ChargingStatusProvider}.
+ */
+ public void stopUsing() {
+ mCallback = null;
+
+ if (mChargingStatusCallback != null) {
+ mKeyguardUpdateMonitor.removeCallback(mChargingStatusCallback);
+ mChargingStatusCallback = null;
+ }
+ }
+
+ private String computeChargingString() {
+ if (!mBatteryState.isValid()) {
+ return null;
+ }
+
+ int chargingId;
+
+ if (mBatteryState.isBatteryDefender()) {
+ return mResources.getString(
+ R.string.keyguard_plugged_in_charging_limited,
+ mBatteryState.getBatteryLevelAsPercentage());
+ } else if (mBatteryState.isPowerCharged()) {
+ return mResources.getString(R.string.keyguard_charged);
+ }
+
+ final long chargingTimeRemaining = mBatteryState.getChargingTimeRemaining(mBatteryInfo);
+ final boolean hasChargingTime = chargingTimeRemaining > 0;
+ if (mBatteryState.isPowerPluggedInWired()) {
+ switch (mBatteryState.getChargingSpeed(mContext)) {
+ case BatteryStatus.CHARGING_FAST:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_fast
+ : R.string.keyguard_plugged_in_charging_fast;
+ break;
+ case BatteryStatus.CHARGING_SLOWLY:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_slowly
+ : R.string.keyguard_plugged_in_charging_slowly;
+ break;
+ default:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time
+ : R.string.keyguard_plugged_in;
+ break;
+ }
+ } else if (mBatteryState.isPowerPluggedInWireless()) {
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_wireless
+ : R.string.keyguard_plugged_in_wireless;
+ } else if (mBatteryState.isPowerPluggedInDocked()) {
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_dock
+ : R.string.keyguard_plugged_in_dock;
+ } else {
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time
+ : R.string.keyguard_plugged_in;
+ }
+
+ final String percentage = mBatteryState.getBatteryLevelAsPercentage();
+ if (hasChargingTime) {
+ final String chargingTimeFormatted =
+ Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+ mContext, chargingTimeRemaining);
+ return mResources.getString(chargingId, chargingTimeFormatted,
+ percentage);
+ } else {
+ return mResources.getString(chargingId, percentage);
+ }
+ }
+
+ private void reportStatusToCallback() {
+ if (mCallback != null) {
+ final boolean shouldShowStatus =
+ mBatteryState.isPowerPluggedIn() || mBatteryState.isBatteryDefenderEnabled();
+ mCallback.onChargingStatusChanged(shouldShowStatus, computeChargingString());
+ }
+ }
+
+ private class ChargingStatusCallback extends KeyguardUpdateMonitorCallback {
+ @Override
+ public void onRefreshBatteryInfo(BatteryStatus status) {
+ mBatteryState.setBatteryStatus(status);
+ reportStatusToCallback();
+ }
+ }
+
+ /***
+ * A callback to be called when the charging status changes.
+ */
+ public interface Callback {
+ /***
+ * Called when the charging status changes.
+ * @param shouldShowStatus Whether or not to show a charging status message.
+ * @param statusMessage A charging status message.
+ */
+ void onChargingStatusChanged(boolean shouldShowStatus, String statusMessage);
+ }
+
+ /***
+ * A wrapper around {@link BatteryStatus} for fetching various properties of the current
+ * battery and charging state.
+ */
+ private static class BatteryState {
+ private BatteryStatus mBatteryStatus;
+
+ public void setBatteryStatus(BatteryStatus batteryStatus) {
+ mBatteryStatus = batteryStatus;
+ }
+
+ public boolean isValid() {
+ return mBatteryStatus != null;
+ }
+
+ public long getChargingTimeRemaining(IBatteryStats batteryInfo) {
+ try {
+ return isPowerPluggedIn() ? batteryInfo.computeChargeTimeRemaining() : -1;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IBatteryStats: ", e);
+ return -1;
+ }
+ }
+
+ public boolean isBatteryDefenderEnabled() {
+ return isValid() && mBatteryStatus.isPluggedIn() && isBatteryDefender();
+ }
+
+ public boolean isBatteryDefender() {
+ return isValid() && mBatteryStatus.isBatteryDefender();
+ }
+
+ public int getBatteryLevel() {
+ return isValid() ? mBatteryStatus.level : 0;
+ }
+
+ public int getChargingSpeed(Context context) {
+ return isValid() ? mBatteryStatus.getChargingSpeed(context) : 0;
+ }
+
+ public boolean isPowerCharged() {
+ return isValid() && mBatteryStatus.isCharged();
+ }
+
+ public boolean isPowerPluggedIn() {
+ return isValid() && mBatteryStatus.isPluggedIn() && isChargingOrFull();
+ }
+
+ public boolean isPowerPluggedInWired() {
+ return isValid()
+ && mBatteryStatus.isPluggedInWired()
+ && isChargingOrFull();
+ }
+
+ public boolean isPowerPluggedInWireless() {
+ return isValid()
+ && mBatteryStatus.isPluggedInWireless()
+ && isChargingOrFull();
+ }
+
+ public boolean isPowerPluggedInDocked() {
+ return isValid() && mBatteryStatus.isPluggedInDock() && isChargingOrFull();
+ }
+
+ private boolean isChargingOrFull() {
+ return isValid()
+ && (mBatteryStatus.status == BatteryManager.BATTERY_STATUS_CHARGING
+ || mBatteryStatus.isCharged());
+ }
+
+ private String getBatteryLevelAsPercentage() {
+ return NumberFormat.getPercentInstance().format(getBatteryLevel() / 100f);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt
new file mode 100644
index 000000000000..4c1da0198498
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/DirectBootCondition.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock
+
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.UserManager
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.shared.condition.Condition
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.cancellable
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+
+class DirectBootCondition
+@Inject
+constructor(
+ broadcastDispatcher: BroadcastDispatcher,
+ private val userManager: UserManager,
+ @Application private val coroutineScope: CoroutineScope,
+) : Condition(coroutineScope) {
+ private var job: Job? = null
+ private val directBootFlow =
+ broadcastDispatcher
+ .broadcastFlow(IntentFilter(Intent.ACTION_USER_UNLOCKED))
+ .map { !userManager.isUserUnlocked }
+ .cancellable()
+ .distinctUntilChanged()
+
+ override fun start() {
+ job = coroutineScope.launch { directBootFlow.collect { updateCondition(it) } }
+ updateCondition(!userManager.isUserUnlocked)
+ }
+
+ override fun stop() {
+ job?.cancel()
+ }
+
+ override fun getStartStrategy(): Int {
+ return START_EAGERLY
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java
new file mode 100644
index 000000000000..7f21d0707f63
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/ForceLowLightCondition.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.dagger.qualifiers.Application;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.statusbar.commandline.Command;
+import com.android.systemui.statusbar.commandline.CommandRegistry;
+
+import kotlinx.coroutines.CoroutineScope;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import javax.inject.Inject;
+
+/**
+ * This condition registers for and fulfills cmd shell commands to force a device into or out of
+ * low-light conditions.
+ */
+public class ForceLowLightCondition extends Condition {
+ /**
+ * Command root
+ */
+ public static final String COMMAND_ROOT = "low-light";
+ /**
+ * Command for forcing device into low light.
+ */
+ public static final String COMMAND_ENABLE_LOW_LIGHT = "enable";
+
+ /**
+ * Command for preventing a device from entering low light.
+ */
+ public static final String COMMAND_DISABLE_LOW_LIGHT = "disable";
+
+ /**
+ * Command for clearing previously forced low-light conditions.
+ */
+ public static final String COMMAND_CLEAR_LOW_LIGHT = "clear";
+
+ private static final String TAG = "ForceLowLightCondition";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ /**
+ * Default Constructor.
+ *
+ * @param commandRegistry command registry to register commands with.
+ */
+ @Inject
+ public ForceLowLightCondition(
+ @Application CoroutineScope scope,
+ CommandRegistry commandRegistry
+ ) {
+ super(scope, null, true);
+
+ if (DEBUG) {
+ Log.d(TAG, "registering commands");
+ }
+ commandRegistry.registerCommand(COMMAND_ROOT, () -> new Command() {
+ @Override
+ public void execute(@NonNull PrintWriter pw, @NonNull List<String> args) {
+ if (args.size() != 1) {
+ pw.println("no command specified");
+ help(pw);
+ return;
+ }
+
+ final String cmd = args.get(0);
+
+ if (TextUtils.equals(cmd, COMMAND_ENABLE_LOW_LIGHT)) {
+ logAndPrint(pw, "forcing low light");
+ updateCondition(true);
+ } else if (TextUtils.equals(cmd, COMMAND_DISABLE_LOW_LIGHT)) {
+ logAndPrint(pw, "forcing to not enter low light");
+ updateCondition(false);
+ } else if (TextUtils.equals(cmd, COMMAND_CLEAR_LOW_LIGHT)) {
+ logAndPrint(pw, "clearing any forced low light");
+ clearCondition();
+ } else {
+ pw.println("invalid command");
+ help(pw);
+ }
+ }
+
+ @Override
+ public void help(@NonNull PrintWriter pw) {
+ pw.println("Usage: adb shell cmd statusbar low-light <cmd>");
+ pw.println("Supported commands:");
+ pw.println(" - enable");
+ pw.println(" forces device into low-light");
+ pw.println(" - disable");
+ pw.println(" forces device to not enter low-light");
+ pw.println(" - clear");
+ pw.println(" clears any previously forced state");
+ }
+
+ private void logAndPrint(PrintWriter pw, String message) {
+ pw.println(message);
+ if (DEBUG) {
+ Log.d(TAG, message);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void start() {
+ }
+
+ @Override
+ protected void stop() {
+ }
+
+ @Override
+ protected int getStartStrategy() {
+ return START_EAGERLY;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockAnimationProvider.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockAnimationProvider.java
new file mode 100644
index 000000000000..6de599803a57
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightClockAnimationProvider.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.app.animation.Interpolators;
+import com.android.dream.lowlight.util.TruncatedInterpolator;
+import com.android.systemui.lowlightclock.dagger.LowLightModule;
+import com.android.systemui.statusbar.CrossFadeHelper;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/***
+ * A class that provides the animations used by the low-light clock.
+ *
+ * The entry and exit animations are opposites, with the only difference being a delay before the
+ * text fades in on entry.
+ */
+public class LowLightClockAnimationProvider {
+ private final int mYTranslationAnimationInStartOffset;
+ private final long mYTranslationAnimationInDurationMillis;
+ private final long mAlphaAnimationInStartDelayMillis;
+ private final long mAlphaAnimationDurationMillis;
+
+ /**
+ * Custom interpolator used for the translate out animation, which uses an emphasized easing
+ * like the translate in animation, but is scaled to match the length of the alpha animation.
+ */
+ private final Interpolator mTranslationOutInterpolator;
+
+ @Inject
+ public LowLightClockAnimationProvider(
+ @Named(LowLightModule.Y_TRANSLATION_ANIMATION_OFFSET)
+ int yTranslationAnimationInStartOffset,
+ @Named(LowLightModule.Y_TRANSLATION_ANIMATION_DURATION_MILLIS)
+ long yTranslationAnimationInDurationMillis,
+ @Named(LowLightModule.ALPHA_ANIMATION_IN_START_DELAY_MILLIS)
+ long alphaAnimationInStartDelayMillis,
+ @Named(LowLightModule.ALPHA_ANIMATION_DURATION_MILLIS)
+ long alphaAnimationDurationMillis) {
+ mYTranslationAnimationInStartOffset = yTranslationAnimationInStartOffset;
+ mYTranslationAnimationInDurationMillis = yTranslationAnimationInDurationMillis;
+ mAlphaAnimationInStartDelayMillis = alphaAnimationInStartDelayMillis;
+ mAlphaAnimationDurationMillis = alphaAnimationDurationMillis;
+
+ mTranslationOutInterpolator = new TruncatedInterpolator(Interpolators.EMPHASIZED,
+ /*originalDuration=*/ mYTranslationAnimationInDurationMillis,
+ /*newDuration=*/ mAlphaAnimationDurationMillis);
+ }
+
+ /***
+ * Provides an animation for when the given views become visible.
+ * @param views Any number of views to animate in together.
+ */
+ public Animator provideAnimationIn(View... views) {
+ final AnimatorSet animatorSet = new AnimatorSet();
+
+ for (View view : views) {
+ if (view == null) continue;
+ // Set the alpha to 0 to start because the alpha animation has a start delay.
+ CrossFadeHelper.fadeOut(view, 0f, false);
+
+ final Animator alphaAnimator =
+ ObjectAnimator.ofFloat(view, View.ALPHA, 1f);
+ alphaAnimator.setStartDelay(mAlphaAnimationInStartDelayMillis);
+ alphaAnimator.setDuration(mAlphaAnimationDurationMillis);
+ alphaAnimator.setInterpolator(Interpolators.LINEAR);
+
+ final Animator positionAnimator = ObjectAnimator
+ .ofFloat(view, View.TRANSLATION_Y, mYTranslationAnimationInStartOffset, 0f);
+ positionAnimator.setDuration(mYTranslationAnimationInDurationMillis);
+ positionAnimator.setInterpolator(Interpolators.EMPHASIZED);
+
+ // The position animator must be started first since the alpha animator has a start
+ // delay.
+ animatorSet.playTogether(positionAnimator, alphaAnimator);
+ }
+
+ return animatorSet;
+ }
+
+ /***
+ * Provides an animation for when the given views are going out of view.
+ * @param views Any number of views to animate out.
+ */
+ public Animator provideAnimationOut(View... views) {
+ final AnimatorSet animatorSet = new AnimatorSet();
+
+ for (View view : views) {
+ if (view == null) continue;
+ final Animator alphaAnimator =
+ ObjectAnimator.ofFloat(view, View.ALPHA, 0f);
+ alphaAnimator.setDuration(mAlphaAnimationDurationMillis);
+ alphaAnimator.setInterpolator(Interpolators.LINEAR);
+
+ final Animator positionAnimator = ObjectAnimator
+ .ofFloat(view, View.TRANSLATION_Y, mYTranslationAnimationInStartOffset);
+ // Use the same duration as the alpha animation plus our custom interpolator.
+ positionAnimator.setDuration(mAlphaAnimationDurationMillis);
+ positionAnimator.setInterpolator(mTranslationOutInterpolator);
+ animatorSet.playTogether(alphaAnimator, positionAnimator);
+ }
+
+ return animatorSet;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java
new file mode 100644
index 000000000000..e91be5028777
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightCondition.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.dagger.qualifiers.Application;
+import com.android.systemui.shared.condition.Condition;
+
+import kotlinx.coroutines.CoroutineScope;
+
+import javax.inject.Inject;
+
+/**
+ * Condition for monitoring when the device enters and exits lowlight mode.
+ */
+public class LowLightCondition extends Condition {
+ private final AmbientLightModeMonitor mAmbientLightModeMonitor;
+ private final UiEventLogger mUiEventLogger;
+
+ @Inject
+ public LowLightCondition(@Application CoroutineScope scope,
+ AmbientLightModeMonitor ambientLightModeMonitor,
+ UiEventLogger uiEventLogger) {
+ super(scope);
+ mAmbientLightModeMonitor = ambientLightModeMonitor;
+ mUiEventLogger = uiEventLogger;
+ }
+
+ @Override
+ protected void start() {
+ mAmbientLightModeMonitor.start(this::onLowLightChanged);
+ }
+
+ @Override
+ protected void stop() {
+ mAmbientLightModeMonitor.stop();
+
+ // Reset condition met to false.
+ updateCondition(false);
+ }
+
+ @Override
+ protected int getStartStrategy() {
+ // As this condition keeps the lowlight sensor active, it should only run when needed.
+ return START_WHEN_NEEDED;
+ }
+
+ private void onLowLightChanged(int lowLightMode) {
+ if (lowLightMode == AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED) {
+ // Ignore undecided mode changes.
+ return;
+ }
+
+ final boolean isLowLight = lowLightMode == AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK;
+ if (isLowLight == isConditionMet()) {
+ // No change in condition, don't do anything.
+ return;
+ }
+ mUiEventLogger.log(isLowLight ? LowLightDockEvent.AMBIENT_LIGHT_TO_DARK
+ : LowLightDockEvent.AMBIENT_LIGHT_TO_LIGHT);
+ updateCondition(isLowLight);
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromNotificationsShadeToQuickSettingsShadeTransition.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightDisplayController.kt
index 9a7f99f3247b..9a9d813b18c5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromNotificationsShadeToQuickSettingsShadeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightDisplayController.kt
@@ -14,16 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.scene.ui.composable.transitions
+package com.android.systemui.lowlightclock
-import androidx.compose.animation.core.tween
-import com.android.compose.animation.scene.TransitionBuilder
-import kotlin.time.Duration.Companion.milliseconds
+interface LowLightDisplayController {
+ fun isDisplayBrightnessModeSupported(): Boolean
-fun TransitionBuilder.notificationsShadeToQuickSettingsShadeTransition(
- durationScale: Double = 1.0
-) {
- spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+ fun setDisplayBrightnessModeEnabled(enabled: Boolean)
}
-
-private val DefaultDuration = 300.milliseconds
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightDockEvent.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightDockEvent.kt
new file mode 100644
index 000000000000..b99aeb6eeacc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightDockEvent.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+enum class LowLightDockEvent(private val id: Int) : UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "Ambient light changed from light to dark") AMBIENT_LIGHT_TO_DARK(999),
+ @UiEvent(doc = "The low light mode has started") LOW_LIGHT_STARTED(1000),
+ @UiEvent(doc = "Ambient light changed from dark to light") AMBIENT_LIGHT_TO_LIGHT(1001),
+ @UiEvent(doc = "The low light mode has stopped") LOW_LIGHT_STOPPED(1002);
+
+ override fun getId(): Int {
+ return id
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightLogger.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightLogger.kt
new file mode 100644
index 000000000000..11d75215edf5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightLogger.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.lowlightclock
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.lowlightclock.dagger.LowLightLog
+import javax.inject.Inject
+
+/** Logs to a {@link LogBuffer} anything related to low-light features. */
+class LowLightLogger @Inject constructor(@LowLightLog private val buffer: LogBuffer) {
+ /** Logs a debug message to the buffer. */
+ fun d(tag: String, message: String) = buffer.log(tag, LogLevel.DEBUG, message)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.java
new file mode 100644
index 000000000000..912ace7675d5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/LowLightMonitor.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_LOW_LIGHT;
+import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_REGULAR;
+import static com.android.systemui.dreams.dagger.DreamModule.LOW_LIGHT_DREAM_SERVICE;
+import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
+import static com.android.systemui.lowlightclock.dagger.LowLightModule.LOW_LIGHT_PRECONDITIONS;
+
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+
+import androidx.annotation.Nullable;
+
+import com.android.dream.lowlight.LowLightDreamManager;
+import com.android.systemui.dagger.qualifiers.SystemUser;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.shared.condition.Monitor;
+import com.android.systemui.util.condition.ConditionalCoreStartable;
+
+import dagger.Lazy;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * Tracks environment (low-light or not) in order to correctly show or hide a low-light clock while
+ * dreaming.
+ */
+public class LowLightMonitor extends ConditionalCoreStartable implements Monitor.Callback,
+ ScreenLifecycle.Observer {
+ private static final String TAG = "LowLightMonitor";
+
+ private final Lazy<LowLightDreamManager> mLowLightDreamManager;
+ private final Monitor mConditionsMonitor;
+ private final Lazy<Set<Condition>> mLowLightConditions;
+ private Monitor.Subscription.Token mSubscriptionToken;
+ private ScreenLifecycle mScreenLifecycle;
+ private final LowLightLogger mLogger;
+
+ private final ComponentName mLowLightDreamService;
+
+ private final PackageManager mPackageManager;
+
+ @Inject
+ public LowLightMonitor(Lazy<LowLightDreamManager> lowLightDreamManager,
+ @SystemUser Monitor conditionsMonitor,
+ @Named(LOW_LIGHT_PRECONDITIONS) Lazy<Set<Condition>> lowLightConditions,
+ ScreenLifecycle screenLifecycle,
+ LowLightLogger lowLightLogger,
+ @Nullable @Named(LOW_LIGHT_DREAM_SERVICE) ComponentName lowLightDreamService,
+ PackageManager packageManager) {
+ super(conditionsMonitor);
+ mLowLightDreamManager = lowLightDreamManager;
+ mConditionsMonitor = conditionsMonitor;
+ mLowLightConditions = lowLightConditions;
+ mScreenLifecycle = screenLifecycle;
+ mLogger = lowLightLogger;
+ mLowLightDreamService = lowLightDreamService;
+ mPackageManager = packageManager;
+ }
+
+ @Override
+ public void onConditionsChanged(boolean allConditionsMet) {
+ mLogger.d(TAG, "Low light enabled: " + allConditionsMet);
+
+ mLowLightDreamManager.get().setAmbientLightMode(allConditionsMet
+ ? AMBIENT_LIGHT_MODE_LOW_LIGHT : AMBIENT_LIGHT_MODE_REGULAR);
+ }
+
+ @Override
+ public void onScreenTurnedOn() {
+ if (mSubscriptionToken == null) {
+ mLogger.d(TAG, "Screen turned on. Subscribing to low light conditions.");
+
+ mSubscriptionToken = mConditionsMonitor.addSubscription(
+ new Monitor.Subscription.Builder(this)
+ .addConditions(mLowLightConditions.get())
+ .build());
+ }
+ }
+
+
+ @Override
+ public void onScreenTurnedOff() {
+ if (mSubscriptionToken != null) {
+ mLogger.d(TAG, "Screen turned off. Removing subscription to low light conditions.");
+
+ mConditionsMonitor.removeSubscription(mSubscriptionToken);
+ mSubscriptionToken = null;
+ }
+ }
+
+ @Override
+ protected void onStart() {
+ if (mLowLightDreamService != null) {
+ // Note that the dream service is disabled by default. This prevents the dream from
+ // appearing in settings on devices that don't have it explicitly excluded (done in
+ // the settings overlay). Therefore, the component is enabled if it is to be used
+ // here.
+ mPackageManager.setComponentEnabledSetting(
+ mLowLightDreamService,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP
+ );
+ } else {
+ // If there is no low light dream service, do not observe conditions.
+ return;
+ }
+
+ mScreenLifecycle.addObserver(this);
+ if (mScreenLifecycle.getScreenState() == SCREEN_ON) {
+ onScreenTurnedOn();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java
new file mode 100644
index 000000000000..fd6ce1762a28
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/ScreenSaverEnabledCondition.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.systemui.dagger.qualifiers.Application;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.util.settings.SecureSettings;
+
+import kotlinx.coroutines.CoroutineScope;
+
+import javax.inject.Inject;
+
+/**
+ * Condition for monitoring if the screensaver setting is enabled.
+ */
+public class ScreenSaverEnabledCondition extends Condition {
+ private static final String TAG = ScreenSaverEnabledCondition.class.getSimpleName();
+
+ private final boolean mScreenSaverEnabledByDefaultConfig;
+ private final SecureSettings mSecureSettings;
+
+ private final ContentObserver mScreenSaverSettingObserver = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateScreenSaverEnabledSetting();
+ }
+ };
+
+ @Inject
+ public ScreenSaverEnabledCondition(@Application CoroutineScope scope, @Main Resources resources,
+ SecureSettings secureSettings) {
+ super(scope);
+ mScreenSaverEnabledByDefaultConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_dreamsEnabledByDefault);
+ mSecureSettings = secureSettings;
+ }
+
+ @Override
+ protected void start() {
+ mSecureSettings.registerContentObserverForUserSync(
+ Settings.Secure.SCREENSAVER_ENABLED,
+ mScreenSaverSettingObserver, UserHandle.USER_CURRENT);
+ updateScreenSaverEnabledSetting();
+ }
+
+ @Override
+ protected void stop() {
+ mSecureSettings.unregisterContentObserverSync(mScreenSaverSettingObserver);
+ }
+
+ @Override
+ protected int getStartStrategy() {
+ return START_EAGERLY;
+ }
+
+ private void updateScreenSaverEnabledSetting() {
+ final boolean enabled = mSecureSettings.getIntForUser(
+ Settings.Secure.SCREENSAVER_ENABLED,
+ mScreenSaverEnabledByDefaultConfig ? 1 : 0,
+ UserHandle.USER_CURRENT) != 0;
+ if (!enabled) {
+ Log.i(TAG, "Disabling low-light clock because screen saver has been disabled");
+ }
+ updateCondition(enabled);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightLog.kt b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightLog.kt
new file mode 100644
index 000000000000..0819664c921c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightLog.kt
@@ -0,0 +1,22 @@
+/*
+ * 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.lowlightclock.dagger
+
+import javax.inject.Qualifier
+
+/** A [com.android.systemui.log.LogBuffer] for logging related to low light features. */
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class LowLightLog
diff --git a/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java
new file mode 100644
index 000000000000..c08be51c0699
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lowlightclock/dagger/LowLightModule.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock.dagger;
+
+import android.content.res.Resources;
+import android.hardware.Sensor;
+
+import com.android.dream.lowlight.dagger.LowLightDreamModule;
+import com.android.systemui.CoreStartable;
+import com.android.systemui.communal.DeviceInactiveCondition;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogBufferFactory;
+import com.android.systemui.lowlightclock.AmbientLightModeMonitor;
+import com.android.systemui.lowlightclock.DirectBootCondition;
+import com.android.systemui.lowlightclock.ForceLowLightCondition;
+import com.android.systemui.lowlightclock.LowLightCondition;
+import com.android.systemui.lowlightclock.LowLightDisplayController;
+import com.android.systemui.lowlightclock.LowLightMonitor;
+import com.android.systemui.lowlightclock.ScreenSaverEnabledCondition;
+import com.android.systemui.res.R;
+import com.android.systemui.shared.condition.Condition;
+
+import dagger.Binds;
+import dagger.BindsOptionalOf;
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.IntoSet;
+
+import javax.inject.Named;
+
+@Module(includes = LowLightDreamModule.class)
+public abstract class LowLightModule {
+ public static final String Y_TRANSLATION_ANIMATION_OFFSET =
+ "y_translation_animation_offset";
+ public static final String Y_TRANSLATION_ANIMATION_DURATION_MILLIS =
+ "y_translation_animation_duration_millis";
+ public static final String ALPHA_ANIMATION_IN_START_DELAY_MILLIS =
+ "alpha_animation_in_start_delay_millis";
+ public static final String ALPHA_ANIMATION_DURATION_MILLIS =
+ "alpha_animation_duration_millis";
+ public static final String LOW_LIGHT_PRECONDITIONS = "low_light_preconditions";
+ public static final String LIGHT_SENSOR = "low_light_monitor_light_sensor";
+
+
+ /**
+ * Provides a {@link LogBuffer} for logs related to low-light features.
+ */
+ @Provides
+ @SysUISingleton
+ @LowLightLog
+ public static LogBuffer provideLowLightLogBuffer(LogBufferFactory factory) {
+ return factory.create("LowLightLog", 250);
+ }
+
+ @Binds
+ @IntoSet
+ @Named(LOW_LIGHT_PRECONDITIONS)
+ abstract Condition bindScreenSaverEnabledCondition(ScreenSaverEnabledCondition condition);
+
+ @Provides
+ @IntoSet
+ @Named(com.android.systemui.lowlightclock.dagger.LowLightModule.LOW_LIGHT_PRECONDITIONS)
+ static Condition provideLowLightCondition(LowLightCondition lowLightCondition,
+ DirectBootCondition directBootCondition) {
+ // Start lowlight if we are either in lowlight or in direct boot. The ordering of the
+ // conditions matters here since we don't want to start the lowlight condition if
+ // we are in direct boot mode.
+ return directBootCondition.or(lowLightCondition);
+ }
+
+ @Binds
+ @IntoSet
+ @Named(LOW_LIGHT_PRECONDITIONS)
+ abstract Condition bindForceLowLightCondition(ForceLowLightCondition condition);
+
+ @Binds
+ @IntoSet
+ @Named(LOW_LIGHT_PRECONDITIONS)
+ abstract Condition bindDeviceInactiveCondition(DeviceInactiveCondition condition);
+
+ @BindsOptionalOf
+ abstract LowLightDisplayController bindsLowLightDisplayController();
+
+ @BindsOptionalOf
+ @Named(LIGHT_SENSOR)
+ abstract Sensor bindsLightSensor();
+
+ @BindsOptionalOf
+ abstract AmbientLightModeMonitor.DebounceAlgorithm bindsDebounceAlgorithm();
+
+ /**
+ *
+ */
+ @Provides
+ @Named(Y_TRANSLATION_ANIMATION_OFFSET)
+ static int providesAnimationInOffset(@Main Resources resources) {
+ return resources.getDimensionPixelOffset(
+ R.dimen.low_light_clock_translate_animation_offset);
+ }
+
+ /**
+ *
+ */
+ @Provides
+ @Named(Y_TRANSLATION_ANIMATION_DURATION_MILLIS)
+ static long providesAnimationDurationMillis(@Main Resources resources) {
+ return resources.getInteger(R.integer.low_light_clock_translate_animation_duration_ms);
+ }
+
+ /**
+ *
+ */
+ @Provides
+ @Named(ALPHA_ANIMATION_IN_START_DELAY_MILLIS)
+ static long providesAlphaAnimationInStartDelayMillis(@Main Resources resources) {
+ return resources.getInteger(R.integer.low_light_clock_alpha_animation_in_start_delay_ms);
+ }
+
+ /**
+ *
+ */
+ @Provides
+ @Named(ALPHA_ANIMATION_DURATION_MILLIS)
+ static long providesAlphaAnimationDurationMillis(@Main Resources resources) {
+ return resources.getInteger(R.integer.low_light_clock_alpha_animation_duration_ms);
+ }
+ /** Inject into LowLightMonitor. */
+ @Binds
+ @IntoMap
+ @ClassKey(LowLightMonitor.class)
+ abstract CoreStartable bindLowLightMonitor(LowLightMonitor lowLightMonitor);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaDataRepository.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaDataRepository.kt
index b6fd287a675e..8e773a5de194 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaDataRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaDataRepository.kt
@@ -36,10 +36,7 @@ private const val DEBUG = true
@SysUISingleton
class MediaDataRepository
@Inject
-constructor(
- private val mediaFlags: MediaFlags,
- dumpManager: DumpManager,
-) : Dumpable {
+constructor(private val mediaFlags: MediaFlags, dumpManager: DumpManager) : Dumpable {
private val _mediaEntries: MutableStateFlow<Map<String, MediaData>> =
MutableStateFlow(LinkedHashMap())
@@ -59,27 +56,6 @@ constructor(
}
/**
- * Marks the recommendation data as inactive.
- *
- * @return true if the recommendation was actually marked as inactive, false otherwise.
- */
- fun setRecommendationInactive(key: String): Boolean {
- if (!mediaFlags.isPersistentSsCardEnabled()) {
- Log.e(TAG, "Only persistent recommendation can be inactive!")
- return false
- }
- if (DEBUG) Log.d(TAG, "Setting smartspace recommendation inactive")
-
- if (smartspaceMediaData.value.targetId != key || !smartspaceMediaData.value.isValid()) {
- // If this doesn't match, or we've already invalidated the data, no action needed
- return false
- }
-
- setRecommendation(smartspaceMediaData.value.copy(isActive = false))
- return true
- }
-
- /**
* Marks the recommendation data as dismissed.
*
* @return true if the recommendation was dismissed or already inactive, false otherwise.
@@ -96,7 +72,7 @@ constructor(
setRecommendation(
SmartspaceMediaData(
targetId = smartspaceMediaData.value.targetId,
- instanceId = smartspaceMediaData.value.instanceId
+ instanceId = smartspaceMediaData.value.instanceId,
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImpl.kt
index 96ef7d250012..6ea161c54aaf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImpl.kt
@@ -76,6 +76,7 @@ constructor(
private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
val listeners: Set<MediaDataManager.Listener>
get() = _listeners.toSet()
+
lateinit var mediaDataManager: MediaDataManager
private val allEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
@@ -107,7 +108,7 @@ constructor(
data: MediaData,
immediately: Boolean,
receivedSmartspaceCardLatency: Int,
- isSsReactivated: Boolean
+ isSsReactivated: Boolean,
) {
if (oldKey != null && oldKey != key) {
allEntries.remove(oldKey)
@@ -133,11 +134,9 @@ constructor(
override fun onSmartspaceMediaDataLoaded(
key: String,
data: SmartspaceMediaData,
- shouldPrioritize: Boolean
+ shouldPrioritize: Boolean,
) {
- // With persistent recommendation card, we could get a background update while inactive
- // Otherwise, consider it an invalid update
- if (!data.isActive && !mediaFlags.isPersistentSsCardEnabled()) {
+ if (!data.isActive) {
Log.d(TAG, "Inactive recommendation data. Skip triggering.")
return
}
@@ -176,7 +175,7 @@ constructor(
logger.logRecommendationActivated(
mediaData.appUid,
mediaData.packageName,
- mediaData.instanceId
+ mediaData.instanceId,
)
listeners.forEach {
it.onMediaDataLoaded(
@@ -186,7 +185,7 @@ constructor(
receivedSmartspaceCardLatency =
(systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis)
.toInt(),
- isSsReactivated = true
+ isSsReactivated = true,
)
}
}
@@ -201,7 +200,7 @@ constructor(
}
logger.logRecommendationAdded(
smartspaceMediaData.packageName,
- smartspaceMediaData.instanceId
+ smartspaceMediaData.instanceId,
)
listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) }
}
@@ -232,7 +231,7 @@ constructor(
smartspaceMediaData =
EMPTY_SMARTSPACE_MEDIA_DATA.copy(
targetId = smartspaceMediaData.targetId,
- instanceId = smartspaceMediaData.instanceId
+ instanceId = smartspaceMediaData.instanceId,
)
}
listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
@@ -286,7 +285,7 @@ constructor(
if (dismissIntent == null) {
Log.w(
TAG,
- "Cannot create dismiss action click action: extras missing dismiss_intent."
+ "Cannot create dismiss action click action: extras missing dismiss_intent.",
)
} else if (
dismissIntent.component?.className == EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME
@@ -297,20 +296,15 @@ constructor(
broadcastSender.sendBroadcast(dismissIntent)
}
- if (mediaFlags.isPersistentSsCardEnabled()) {
- smartspaceMediaData = smartspaceMediaData.copy(isActive = false)
- mediaDataManager.setRecommendationInactive(smartspaceMediaData.targetId)
- } else {
- smartspaceMediaData =
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(
- targetId = smartspaceMediaData.targetId,
- instanceId = smartspaceMediaData.instanceId,
- )
- mediaDataManager.dismissSmartspaceRecommendation(
- smartspaceMediaData.targetId,
- delay = 0L,
+ smartspaceMediaData =
+ EMPTY_SMARTSPACE_MEDIA_DATA.copy(
+ targetId = smartspaceMediaData.targetId,
+ instanceId = smartspaceMediaData.instanceId,
)
- }
+ mediaDataManager.dismissSmartspaceRecommendation(
+ smartspaceMediaData.targetId,
+ delay = 0L,
+ )
}
}
@@ -322,12 +316,7 @@ constructor(
/** Are there any media entries we should display? */
fun hasAnyMediaOrRecommendation(): Boolean {
- val hasSmartspace =
- if (mediaFlags.isPersistentSsCardEnabled()) {
- smartspaceMediaData.isValid()
- } else {
- smartspaceMediaData.isActive && smartspaceMediaData.isValid()
- }
+ val hasSmartspace = smartspaceMediaData.isActive && smartspaceMediaData.isValid()
return userEntries.isNotEmpty() || hasSmartspace
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
index f1f299aac2b4..3eac12d2b24c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
@@ -70,8 +70,6 @@ import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Comp
import com.android.systemui.media.controls.domain.resume.MediaResumeListener
import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
import com.android.systemui.media.controls.shared.MediaLogger
-import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
-import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
import com.android.systemui.media.controls.shared.model.MediaAction
import com.android.systemui.media.controls.shared.model.MediaButton
import com.android.systemui.media.controls.shared.model.MediaData
@@ -769,23 +767,6 @@ class LegacyMediaDataManagerImpl(
)
}
- /** Called when the recommendation card should no longer be visible in QQS or lockscreen */
- override fun setRecommendationInactive(key: String) {
- if (!mediaFlags.isPersistentSsCardEnabled()) {
- Log.e(TAG, "Only persistent recommendation can be inactive!")
- return
- }
- if (DEBUG) Log.d(TAG, "Setting smartspace recommendation inactive")
-
- if (smartspaceMediaData.targetId != key || !smartspaceMediaData.isValid()) {
- // If this doesn't match, or we've already invalidated the data, no action needed
- return
- }
-
- smartspaceMediaData = smartspaceMediaData.copy(isActive = false)
- notifySmartspaceMediaDataLoaded(smartspaceMediaData.targetId, smartspaceMediaData)
- }
-
private suspend fun loadMediaDataForResumption(
userId: Int,
desc: MediaDescription,
@@ -1268,13 +1249,21 @@ class LegacyMediaDataManagerImpl(
}
private fun getResumeMediaAction(action: Runnable): MediaAction {
+ val iconId =
+ if (Flags.mediaControlsUiUpdate()) {
+ R.drawable.ic_media_play_button
+ } else {
+ R.drawable.ic_media_play
+ }
return MediaAction(
- Icon.createWithResource(context, R.drawable.ic_media_play)
- .setTint(themeText)
- .loadDrawable(context),
+ Icon.createWithResource(context, iconId).setTint(themeText).loadDrawable(context),
action,
context.getString(R.string.controls_media_resume),
- context.getDrawable(R.drawable.ic_media_play_container),
+ if (Flags.mediaControlsUiUpdate()) {
+ context.getDrawable(R.drawable.ic_media_play_button_container)
+ } else {
+ context.getDrawable(R.drawable.ic_media_play_container)
+ },
)
}
@@ -1490,15 +1479,7 @@ class LegacyMediaDataManagerImpl(
val dismissIntent =
baseAction?.extras?.getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY) as Intent?
- val isActive =
- when {
- !mediaFlags.isPersistentSsCardEnabled() -> true
- baseAction == null -> true
- else -> {
- val triggerSource = baseAction.extras?.getString(EXTRA_KEY_TRIGGER_SOURCE)
- triggerSource != EXTRA_VALUE_TRIGGER_PERIODIC
- }
- }
+ val isActive = true
packageName(target)?.let {
return SmartspaceMediaData(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
index 68f1af311b1b..4c0312fb4fa3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
@@ -103,7 +103,7 @@ constructor(
data: MediaData,
immediately: Boolean,
receivedSmartspaceCardLatency: Int,
- isSsReactivated: Boolean
+ isSsReactivated: Boolean,
) {
if (oldKey != null && oldKey != key) {
mediaFilterRepository.removeMediaEntry(oldKey)
@@ -122,7 +122,7 @@ constructor(
mediaLogger.logMediaLoaded(data.instanceId, data.active, "loading media")
mediaFilterRepository.addMediaDataLoadingState(
MediaDataLoadingModel.Loaded(data.instanceId),
- isUpdate
+ isUpdate,
)
// Notify listeners
@@ -132,11 +132,9 @@ constructor(
override fun onSmartspaceMediaDataLoaded(
key: String,
data: SmartspaceMediaData,
- shouldPrioritize: Boolean
+ shouldPrioritize: Boolean,
) {
- // With persistent recommendation card, we could get a background update while inactive
- // Otherwise, consider it an invalid update
- if (!data.isActive && !mediaFlags.isPersistentSsCardEnabled()) {
+ if (!data.isActive) {
Log.d(TAG, "Inactive recommendation data. Skip triggering.")
return
}
@@ -179,7 +177,7 @@ constructor(
logger.logRecommendationActivated(
mediaData.appUid,
mediaData.packageName,
- mediaData.instanceId
+ mediaData.instanceId,
)
mediaFilterRepository.addMediaDataLoadingState(
MediaDataLoadingModel.Loaded(
@@ -187,13 +185,13 @@ constructor(
receivedSmartspaceCardLatency =
(systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis)
.toInt(),
- isSsReactivated = true
+ isSsReactivated = true,
)
)
mediaLogger.logMediaLoaded(
mediaData.instanceId,
mediaData.active,
- "reactivating media instead of smartspace"
+ "reactivating media instead of smartspace",
)
listeners.forEach { listener ->
getKey(lastActiveId)?.let { lastActiveKey ->
@@ -205,7 +203,7 @@ constructor(
(systemClock.currentTimeMillis() -
data.headphoneConnectionTimeMillis)
.toInt(),
- isSsReactivated = true
+ isSsReactivated = true,
)
}
}
@@ -222,7 +220,7 @@ constructor(
val smartspaceMediaData = mediaFilterRepository.smartspaceMediaData.value
logger.logRecommendationAdded(
smartspaceMediaData.packageName,
- smartspaceMediaData.instanceId
+ smartspaceMediaData.instanceId,
)
mediaFilterRepository.setRecommendationsLoadingState(
SmartspaceMediaLoadingModel.Loaded(key, shouldPrioritizeMutable)
@@ -268,7 +266,7 @@ constructor(
mediaFilterRepository.setRecommendation(
EMPTY_SMARTSPACE_MEDIA_DATA.copy(
targetId = smartspaceMediaData.targetId,
- instanceId = smartspaceMediaData.instanceId
+ instanceId = smartspaceMediaData.instanceId,
)
)
}
@@ -317,12 +315,12 @@ constructor(
val isUpdate = mediaFilterRepository.addSelectedUserMediaEntry(data)
mediaFilterRepository.addMediaDataLoadingState(
MediaDataLoadingModel.Loaded(data.instanceId),
- isUpdate
+ isUpdate,
)
mediaLogger.logMediaLoaded(
data.instanceId,
data.active,
- "Re-adding $key after user change"
+ "Re-adding $key after user change",
)
listenersCopy.forEach { listener -> listener.onMediaDataLoaded(key, null, data) }
}
@@ -346,7 +344,7 @@ constructor(
if (dismissIntent == null) {
Log.w(
TAG,
- "Cannot create dismiss action click action: extras missing dismiss_intent."
+ "Cannot create dismiss action click action: extras missing dismiss_intent.",
)
} else if (
dismissIntent.component?.className == EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME
@@ -357,21 +355,16 @@ constructor(
broadcastSender.sendBroadcast(dismissIntent)
}
- if (mediaFlags.isPersistentSsCardEnabled()) {
- mediaFilterRepository.setRecommendation(smartspaceMediaData.copy(isActive = false))
- mediaDataProcessor.setRecommendationInactive(smartspaceMediaData.targetId)
- } else {
- mediaFilterRepository.setRecommendation(
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(
- targetId = smartspaceMediaData.targetId,
- instanceId = smartspaceMediaData.instanceId,
- )
- )
- mediaDataProcessor.dismissSmartspaceRecommendation(
- smartspaceMediaData.targetId,
- delay = 0L,
+ mediaFilterRepository.setRecommendation(
+ EMPTY_SMARTSPACE_MEDIA_DATA.copy(
+ targetId = smartspaceMediaData.targetId,
+ instanceId = smartspaceMediaData.instanceId,
)
- }
+ )
+ mediaDataProcessor.dismissSmartspaceRecommendation(
+ smartspaceMediaData.targetId,
+ delay = 0L,
+ )
}
}
@@ -421,7 +414,7 @@ constructor(
get() =
SystemProperties.getLong(
"debug.sysui.smartspace_max_age",
- TimeUnit.MINUTES.toMillis(30)
+ TimeUnit.MINUTES.toMillis(30),
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
index a176e0c1c2a6..8bb7303a8386 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
@@ -43,7 +43,9 @@ import android.support.v4.media.MediaMetadataCompat
import android.text.TextUtils
import android.util.Log
import androidx.media.utils.MediaConstants
+import com.android.app.tracing.coroutines.asyncTraced as async
import com.android.app.tracing.coroutines.traceCoroutine
+import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
@@ -67,7 +69,6 @@ import kotlin.coroutines.coroutineContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
-import com.android.app.tracing.coroutines.asyncTraced as async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
@@ -511,13 +512,21 @@ constructor(
sbn.notification.extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)
private fun getResumeMediaAction(action: Runnable): MediaAction {
+ val iconId =
+ if (Flags.mediaControlsUiUpdate()) {
+ R.drawable.ic_media_play_button
+ } else {
+ R.drawable.ic_media_play
+ }
return MediaAction(
- Icon.createWithResource(context, R.drawable.ic_media_play)
- .setTint(themeText)
- .loadDrawable(context),
+ Icon.createWithResource(context, iconId).setTint(themeText).loadDrawable(context),
action,
context.getString(R.string.controls_media_resume),
- context.getDrawable(R.drawable.ic_media_play_container),
+ if (Flags.mediaControlsUiUpdate()) {
+ context.getDrawable(R.drawable.ic_media_play_button_container)
+ } else {
+ context.getDrawable(R.drawable.ic_media_play_container)
+ },
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt
index 8099e593b33d..c3182bf7a320 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataManager.kt
@@ -56,7 +56,7 @@ interface MediaDataManager {
token: MediaSession.Token,
appName: String,
appIntent: PendingIntent,
- packageName: String
+ packageName: String,
)
/** Dismiss a media entry. Returns false if the key was not found. */
@@ -68,9 +68,6 @@ interface MediaDataManager {
*/
fun dismissSmartspaceRecommendation(key: String, delay: Long)
- /** Called when the recommendation card should no longer be visible in QQS or lockscreen */
- fun setRecommendationInactive(key: String)
-
/** Invoked when notification is removed. */
fun onNotificationRemoved(key: String)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
index a524db4437a5..1464849156dc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
@@ -71,8 +71,6 @@ import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Comp
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
import com.android.systemui.media.controls.shared.MediaLogger
-import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
-import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
import com.android.systemui.media.controls.shared.model.MediaAction
import com.android.systemui.media.controls.shared.model.MediaButton
import com.android.systemui.media.controls.shared.model.MediaData
@@ -613,14 +611,6 @@ class MediaDataProcessor(
}
}
- /** Called when the recommendation card should no longer be visible in QQS or lockscreen */
- fun setRecommendationInactive(key: String) {
- if (mediaDataRepository.setRecommendationInactive(key)) {
- val recommendation = mediaDataRepository.smartspaceMediaData.value
- notifySmartspaceMediaDataLoaded(recommendation.targetId, recommendation)
- }
- }
-
private suspend fun loadMediaDataForResumption(
userId: Int,
desc: MediaDescription,
@@ -1197,13 +1187,21 @@ class MediaDataProcessor(
}
private fun getResumeMediaAction(action: Runnable): MediaAction {
+ val iconId =
+ if (Flags.mediaControlsUiUpdate()) {
+ R.drawable.ic_media_play_button
+ } else {
+ R.drawable.ic_media_play
+ }
return MediaAction(
- Icon.createWithResource(context, R.drawable.ic_media_play)
- .setTint(themeText)
- .loadDrawable(context),
+ Icon.createWithResource(context, iconId).setTint(themeText).loadDrawable(context),
action,
context.getString(R.string.controls_media_resume),
- context.getDrawable(R.drawable.ic_media_play_container),
+ if (Flags.mediaControlsUiUpdate()) {
+ context.getDrawable(R.drawable.ic_media_play_button_container)
+ } else {
+ context.getDrawable(R.drawable.ic_media_play_container)
+ },
)
}
@@ -1451,15 +1449,7 @@ class MediaDataProcessor(
?.extras
?.getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY, Intent::class.java)
- val isActive =
- when {
- !mediaFlags.isPersistentSsCardEnabled() -> true
- baseAction == null -> true
- else -> {
- val triggerSource = baseAction.extras?.getString(EXTRA_KEY_TRIGGER_SOURCE)
- triggerSource != EXTRA_VALUE_TRIGGER_PERIODIC
- }
- }
+ val isActive = true
packageName(target)?.let {
return SmartspaceMediaData(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
index 39cedc36dbec..684a560b0502 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
@@ -180,30 +180,6 @@ constructor(
mediaListeners.remove(key)?.destroy()
}
- override fun onSmartspaceMediaDataLoaded(
- key: String,
- data: SmartspaceMediaData,
- shouldPrioritize: Boolean,
- ) {
- if (!mediaFlags.isPersistentSsCardEnabled()) return
-
- // First check if we already have a listener
- recommendationListeners.get(key)?.let {
- if (!it.destroyed) {
- it.recommendationData = data
- return
- }
- }
-
- // Otherwise, create a new one
- recommendationListeners[key] = RecommendationListener(key, data)
- }
-
- override fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
- if (!mediaFlags.isPersistentSsCardEnabled()) return
- recommendationListeners.remove(key)?.destroy()
- }
-
fun isTimedOut(key: String): Boolean {
return mediaListeners[key]?.timedOut ?: false
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
index 270ab72e291d..891b85225577 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
@@ -41,14 +41,12 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
/** Encapsulates business logic for media pipeline. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MediaCarouselInteractor
@Inject
@@ -70,7 +68,7 @@ constructor(
combine(
mediaFilterRepository.selectedUserEntries,
mediaFilterRepository.smartspaceMediaData,
- mediaFilterRepository.reactivatedId
+ mediaFilterRepository.reactivatedId,
) { entries, smartspaceMediaData, reactivatedKey ->
entries.any { it.value.active } ||
(smartspaceMediaData.isActive &&
@@ -86,14 +84,10 @@ constructor(
val hasAnyMediaOrRecommendation: StateFlow<Boolean> =
combine(
mediaFilterRepository.selectedUserEntries,
- mediaFilterRepository.smartspaceMediaData
+ mediaFilterRepository.smartspaceMediaData,
) { entries, smartspaceMediaData ->
entries.isNotEmpty() ||
- (if (mediaFlags.isPersistentSsCardEnabled()) {
- smartspaceMediaData.isValid()
- } else {
- smartspaceMediaData.isActive && smartspaceMediaData.isValid()
- })
+ (smartspaceMediaData.isActive && smartspaceMediaData.isValid())
}
.stateIn(
scope = applicationScope,
@@ -170,7 +164,7 @@ constructor(
token: MediaSession.Token,
appName: String,
appIntent: PendingIntent,
- packageName: String
+ packageName: String,
) {
mediaDataProcessor.addResumptionControls(
userId,
@@ -179,7 +173,7 @@ constructor(
token,
appName,
appIntent,
- packageName
+ packageName,
)
}
@@ -195,8 +189,6 @@ constructor(
return mediaDataProcessor.dismissSmartspaceRecommendation(key, delay)
}
- override fun setRecommendationInactive(key: String) = unsupported
-
override fun onNotificationRemoved(key: String) {
mediaDataProcessor.onNotificationRemoved(key)
}
@@ -230,7 +222,7 @@ constructor(
mediaFilterRepository.logSmartspaceCardSeen(
MediaSmartspaceLogger.getSurface(location),
visibleIndex,
- isMediaCardUpdate
+ isMediaCardUpdate,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaControlDrawables.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaControlDrawables.kt
index 95ca11c9b451..ec329d3f9d0b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaControlDrawables.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaControlDrawables.kt
@@ -18,7 +18,7 @@ package com.android.systemui.media.controls.shared
import android.content.Context
import android.graphics.drawable.Drawable
-import com.android.systemui.Flags.mediaControlsDrawablesReuse
+import com.android.systemui.Flags.mediaControlsDrawablesReuseBugfix
import com.android.systemui.res.R
object MediaControlDrawables {
@@ -34,21 +34,21 @@ object MediaControlDrawables {
private var homeDevices: Drawable? = null
fun getNextIcon(context: Context): Drawable? {
- if (!mediaControlsDrawablesReuse()) {
+ if (!mediaControlsDrawablesReuseBugfix()) {
return context.getDrawable(R.drawable.ic_media_next)
}
return nextIcon ?: context.getDrawable(R.drawable.ic_media_next).also { nextIcon = it }
}
fun getPrevIcon(context: Context): Drawable? {
- if (!mediaControlsDrawablesReuse()) {
+ if (!mediaControlsDrawablesReuseBugfix()) {
return context.getDrawable(R.drawable.ic_media_prev)
}
return prevIcon ?: context.getDrawable(R.drawable.ic_media_prev).also { prevIcon = it }
}
fun getLeAudioSharing(context: Context): Drawable? {
- if (!mediaControlsDrawablesReuse()) {
+ if (!mediaControlsDrawablesReuseBugfix()) {
return context.getDrawable(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing)
}
return leAudioSharing
@@ -58,7 +58,7 @@ object MediaControlDrawables {
}
fun getAntenna(context: Context): Drawable? {
- if (!mediaControlsDrawablesReuse()) {
+ if (!mediaControlsDrawablesReuseBugfix()) {
return context.getDrawable(R.drawable.settings_input_antenna)
}
return antenna
@@ -66,7 +66,7 @@ object MediaControlDrawables {
}
fun getGroupDevice(context: Context): Drawable? {
- if (!mediaControlsDrawablesReuse()) {
+ if (!mediaControlsDrawablesReuseBugfix()) {
return context.getDrawable(com.android.settingslib.R.drawable.ic_media_group_device)
}
return groupDevice
@@ -76,7 +76,7 @@ object MediaControlDrawables {
}
fun getHomeDevices(context: Context): Drawable? {
- if (!mediaControlsDrawablesReuse()) {
+ if (!mediaControlsDrawablesReuseBugfix()) {
return context.getDrawable(R.drawable.ic_media_home_devices)
}
return homeDevices
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index 47161191b229..f05029b2d55f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -106,7 +106,6 @@ import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.collectLatest
@@ -127,7 +126,6 @@ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
* Class that is responsible for keeping the view carousel up to date. This also handles changes in
* state and applies them to the media carousel like the expansion.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MediaCarouselController
@Inject
@@ -616,12 +614,8 @@ constructor(
logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded)
}
} else {
- if (!mediaFlags.isPersistentSsCardEnabled()) {
- // Handle update to inactive as a removal
- onSmartspaceMediaDataRemoved(data.targetId, immediately = true)
- } else {
- addSmartspaceMediaRecommendations(key, data, shouldPrioritize)
- }
+ // Handle update to inactive as a removal
+ onSmartspaceMediaDataRemoved(data.targetId, immediately = true)
}
MediaPlayerData.isSwipedAway = false
}
@@ -1127,18 +1121,6 @@ constructor(
traceSection("MediaCarouselController#addSmartspaceMediaRecommendations") {
if (DEBUG) Log.d(TAG, "Updating smartspace target in carousel")
MediaPlayerData.getMediaPlayer(key)?.let {
- if (mediaFlags.isPersistentSsCardEnabled()) {
- // The card exists, but could have changed active state, so update for sorting
- MediaPlayerData.addMediaRecommendation(
- key,
- data,
- it,
- shouldPrioritize,
- systemClock,
- debugLogger,
- update = true,
- )
- }
Log.w(TAG, "Skip adding smartspace target in carousel")
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index dccf61d4e6c7..2bf6a10c5258 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -435,6 +435,12 @@ public class MediaControlPanel {
}
this.mIsSeekBarEnabled = isSeekBarEnabled;
updateSeekBarVisibility();
+ mMainExecutor.execute(() -> {
+ if (!mMetadataAnimationHandler.isRunning()) {
+ // Trigger a state refresh so that we immediately update visibilities.
+ mMediaViewController.refreshState();
+ }
+ });
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index a6aa159692ec..1f70ac946da0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -67,7 +67,6 @@ import com.android.systemui.util.settings.SecureSettings
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -99,7 +98,6 @@ val View.isShownNotFaded: Boolean
* This manager is responsible for placement of the unique media view between the different hosts
* and animate the positions of the views to achieve seamless transitions.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MediaHierarchyManager
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
index 975f8f45f9c4..c00e14c5957e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
@@ -225,6 +225,12 @@ constructor(
if (isSeekBarEnabled == enabled) return
isSeekBarEnabled = enabled
MediaControlViewBinder.updateSeekBarVisibility(expandedLayout, isSeekBarEnabled)
+ mainExecutor.execute {
+ if (!metadataAnimationHandler.isRunning) {
+ // Trigger a state refresh so that we immediately update visibilities.
+ refreshState()
+ }
+ }
}
}
@@ -899,7 +905,11 @@ constructor(
// If the view isn't bound, we can drop the animation, otherwise we'll execute it
animateNextStateChange = false
if (transitionLayout == null) {
- logger.logMediaLocation("setCurrentState: view not bound", startLocation, endLocation)
+ logger.logMediaLocation(
+ "setCurrentState: view not bound",
+ startLocation,
+ endLocation,
+ )
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
index b2137afa05e6..4bdcfea6485e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
@@ -167,14 +167,11 @@ constructor(
): MediaCommonViewModel.MediaRecommendations {
return mediaRecs?.copy(
key = commonModel.recsLoadingModel.key,
- loadingEnabled =
- interactor.isRecommendationActive() || mediaFlags.isPersistentSsCardEnabled(),
+ loadingEnabled = interactor.isRecommendationActive(),
)
?: MediaCommonViewModel.MediaRecommendations(
key = commonModel.recsLoadingModel.key,
- loadingEnabled =
- interactor.isRecommendationActive() ||
- mediaFlags.isPersistentSsCardEnabled(),
+ loadingEnabled = interactor.isRecommendationActive(),
recsViewModel = recommendationsViewModel,
onAdded = { commonViewModel ->
mediaLogger.logMediaRecommendationCardAdded(
@@ -217,9 +214,7 @@ constructor(
commonViewModel: MediaCommonViewModel.MediaRecommendations
) {
if (!interactor.isRecommendationActive()) {
- if (!mediaFlags.isPersistentSsCardEnabled()) {
- commonViewModel.onRemoved(true)
- }
+ commonViewModel.onRemoved(true)
}
}
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 ac60c47ee6ab..172998e09266 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
@@ -49,10 +49,6 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlagsClass
/** Check whether to get progress information for resume players */
fun isResumeProgressEnabled() = featureFlags.isEnabled(FlagsClassic.MEDIA_RESUME_PROGRESS)
- /** If true, do not automatically dismiss the recommendation card */
- fun isPersistentSsCardEnabled() =
- featureFlags.isEnabled(FlagsClassic.MEDIA_RETAIN_RECOMMENDATIONS)
-
/** Check whether we allow remote media to generate resume controls */
fun isRemoteResumeAllowed() = featureFlags.isEnabled(FlagsClassic.MEDIA_REMOTE_RESUME)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 0ada931aea43..53f3b3a7a59d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -28,7 +28,6 @@ import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.CheckBox;
import android.widget.TextView;
@@ -159,12 +158,12 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
&& !mController.hasAdjustVolumeUserRestriction()) {
setUpDeviceIcon(device);
updateProgressBarColor();
- setSingleLineLayout(getItemTitle(device), false /* showSeekBar*/,
+ setSingleLineLayout(device.getName(), false /* showSeekBar*/,
true /* showProgressBar */, false /* showCheckBox */,
false /* showEndTouchArea */);
} else {
setUpDeviceIcon(device);
- setSingleLineLayout(getItemTitle(device));
+ setSingleLineLayout(device.getName());
}
} else {
// Set different layout for each device
@@ -173,7 +172,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
updateUnmutedVolumeIcon(device);
mCurrentActivePosition = position;
updateFullItemClickListener(v -> onItemClick(v, device));
- setSingleLineLayout(getItemTitle(device));
+ setSingleLineLayout(device.getName());
initFakeActiveDevice(device);
} else if (device.hasSubtext()) {
boolean isActiveWithOngoingSession =
@@ -185,14 +184,14 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mCurrentActivePosition = position;
updateUnmutedVolumeIcon(device);
mSubTitleText.setText(device.getSubtextString());
- updateTwoLineLayoutContentAlpha(DEVICE_CONNECTED_ALPHA);
+ updateContentAlpha(DEVICE_CONNECTED_ALPHA);
updateEndClickAreaAsSessionEditing(device,
isHost ? R.drawable.media_output_status_edit_session
: R.drawable.ic_sound_bars_anim);
- setTwoLineLayout(device, null /* title */, true /* bFocused */,
+ setTwoLineLayout(device.getName() /* title */,
true /* showSeekBar */, false /* showProgressBar */,
true /* showSubtitle */, false /* showStatus */,
- true /* showEndTouchArea */, false /* isFakeActive */);
+ true /* showEndTouchArea */);
initSeekbar(device, isCurrentSeekbarInvisible);
} else {
if (currentlyConnected) {
@@ -211,27 +210,26 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
if (deviceStatusIcon != null) {
updateDeviceStatusIcon(deviceStatusIcon);
}
- updateTwoLineLayoutContentAlpha(
+ updateContentAlpha(
updateClickActionBasedOnSelectionBehavior(device)
? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
- setTwoLineLayout(device, currentlyConnected /* bFocused */,
+ setTwoLineLayout(device.getName(),
currentlyConnected /* showSeekBar */,
false /* showProgressBar */, true /* showSubtitle */,
- deviceStatusIcon != null /* showStatus */,
- false /* isFakeActive */);
+ deviceStatusIcon != null /* showStatus */);
}
} else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
setUpDeviceIcon(device);
updateConnectionFailedStatusIcon();
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
updateFullItemClickListener(v -> onItemClick(v, device));
- setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */,
+ setTwoLineLayout(device.getName(), false /* showSeekBar */,
false /* showProgressBar */, true /* showSubtitle */,
- true /* showStatus */, false /*isFakeActive*/);
+ true /* showStatus */);
} else if (device.getState() == MediaDeviceState.STATE_GROUPING) {
setUpDeviceIcon(device);
updateProgressBarColor();
- setSingleLineLayout(getItemTitle(device), false /* showSeekBar*/,
+ setSingleLineLayout(device.getName(), false /* showSeekBar*/,
true /* showProgressBar */, false /* showCheckBox */,
false /* showEndTouchArea */);
} else if (mController.getSelectedMediaDevice().size() > 1
@@ -244,7 +242,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
updateEndClickArea(device, isDeviceDeselectable);
disableFocusPropertyForView(mContainerLayout);
setUpContentDescriptionForView(mSeekBar, device);
- setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+ setSingleLineLayout(device.getName(), true /* showSeekBar */,
false /* showProgressBar */, true /* showCheckBox */,
true /* showEndTouchArea */);
initSeekbar(device, isCurrentSeekbarInvisible);
@@ -256,7 +254,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
// mark as disconnected and set special click listener
setUpDeviceIcon(device);
updateFullItemClickListener(v -> cancelMuteAwaitConnection());
- setSingleLineLayout(getItemTitle(device));
+ setSingleLineLayout(device.getName());
} else if (device.hasOngoingSession()) {
mCurrentActivePosition = position;
updateUnmutedVolumeIcon(device);
@@ -264,7 +262,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
? R.drawable.media_output_status_edit_session
: R.drawable.ic_sound_bars_anim);
mEndClickIcon.setVisibility(View.VISIBLE);
- setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+ setSingleLineLayout(device.getName(), true /* showSeekBar */,
false /* showProgressBar */, false /* showCheckBox */,
true /* showEndTouchArea */);
initSeekbar(device, isCurrentSeekbarInvisible);
@@ -279,7 +277,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
updateEndClickArea(device, isDeviceDeselectable);
disableFocusPropertyForView(mContainerLayout);
setUpContentDescriptionForView(mSeekBar, device);
- setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+ setSingleLineLayout(device.getName(), true /* showSeekBar */,
false /* showProgressBar */, true /* showCheckBox */,
true /* showEndTouchArea */);
initSeekbar(device, isCurrentSeekbarInvisible);
@@ -288,7 +286,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
disableFocusPropertyForView(mContainerLayout);
setUpContentDescriptionForView(mSeekBar, device);
mCurrentActivePosition = position;
- setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+ setSingleLineLayout(device.getName(), true /* showSeekBar */,
false /* showProgressBar */, false /* showCheckBox */,
false /* showEndTouchArea */);
initSeekbar(device, isCurrentSeekbarInvisible);
@@ -299,12 +297,12 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
updateGroupableCheckBox(false, true, device);
updateEndClickArea(device, true);
updateFullItemClickListener(v -> onItemClick(v, device));
- setSingleLineLayout(getItemTitle(device), false /* showSeekBar */,
+ setSingleLineLayout(device.getName(), false /* showSeekBar */,
false /* showProgressBar */, true /* showCheckBox */,
true /* showEndTouchArea */);
} else {
setUpDeviceIcon(device);
- setSingleLineLayout(getItemTitle(device));
+ setSingleLineLayout(device.getName());
Drawable deviceStatusIcon =
device.hasOngoingSession() ? mContext.getDrawable(
R.drawable.ic_sound_bars_anim)
@@ -315,7 +313,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
updateDeviceStatusIcon(deviceStatusIcon);
mStatusIcon.setVisibility(View.VISIBLE);
}
- updateSingleLineLayoutContentAlpha(
+ updateContentAlpha(
updateClickActionBasedOnSelectionBehavior(device)
? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
}
@@ -329,16 +327,10 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
ColorStateList(states, colors));
}
- private void updateTwoLineLayoutContentAlpha(float alphaValue) {
- mSubTitleText.setAlpha(alphaValue);
- mTitleIcon.setAlpha(alphaValue);
- mTwoLineTitleText.setAlpha(alphaValue);
- mStatusIcon.setAlpha(alphaValue);
- }
-
- private void updateSingleLineLayoutContentAlpha(float alphaValue) {
+ private void updateContentAlpha(float alphaValue) {
mTitleIcon.setAlpha(alphaValue);
mTitleText.setAlpha(alphaValue);
+ mSubTitleText.setAlpha(alphaValue);
mStatusIcon.setAlpha(alphaValue);
}
@@ -427,8 +419,6 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mTitleIcon.setImageDrawable(addDrawable);
mTitleIcon.setImageTintList(
ColorStateList.valueOf(mController.getColorItemContent()));
- mIconAreaLayout.setBackgroundTintList(
- ColorStateList.valueOf(mController.getColorItemBackground()));
mContainerLayout.setOnClickListener(mController::launchBluetoothPairing);
}
@@ -494,13 +484,6 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
== MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
? R.string.accessibility_bluetooth_name
: R.string.accessibility_cast_name, device.getName()));
- view.setAccessibilityDelegate(new View.AccessibilityDelegate() {
- public void onInitializeAccessibilityNodeInfo(View host,
- AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
- host.setOnClickListener(null);
- }
- });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 1a2238cfbc9e..9b24c69cac30 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -16,14 +16,11 @@
package com.android.systemui.media.dialog;
-import static com.android.systemui.media.dialog.MediaOutputSeekbar.VOLUME_PERCENTAGE_SCALE_SIZE;
-
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.WallpaperColors;
import android.content.Context;
import android.content.res.ColorStateList;
-import android.graphics.Typeface;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
@@ -37,7 +34,6 @@ import android.view.animation.LinearInterpolator;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
@@ -95,10 +91,6 @@ public abstract class MediaOutputBaseAdapter extends
mController.setCurrentColorScheme(wallpaperColors, isDarkTheme);
}
- CharSequence getItemTitle(MediaDevice device) {
- return device.getName();
- }
-
boolean isCurrentlyConnected(MediaDevice device) {
return TextUtils.equals(device.getId(),
mController.getCurrentConnectedMediaDevice().getId())
@@ -138,12 +130,10 @@ public abstract class MediaOutputBaseAdapter extends
final FrameLayout mItemLayout;
final FrameLayout mIconAreaLayout;
final TextView mTitleText;
- final TextView mTwoLineTitleText;
final TextView mSubTitleText;
final TextView mVolumeValueText;
final ImageView mTitleIcon;
final ProgressBar mProgressBar;
- final LinearLayout mTwoLineLayout;
final ImageView mStatusIcon;
final CheckBox mCheckBox;
final ViewGroup mEndTouchArea;
@@ -161,8 +151,6 @@ public abstract class MediaOutputBaseAdapter extends
mItemLayout = view.requireViewById(R.id.item_layout);
mTitleText = view.requireViewById(R.id.title);
mSubTitleText = view.requireViewById(R.id.subtitle);
- mTwoLineLayout = view.requireViewById(R.id.two_line_layout);
- mTwoLineTitleText = view.requireViewById(R.id.two_line_title);
mTitleIcon = view.requireViewById(R.id.title_icon);
mProgressBar = view.requireViewById(R.id.volume_indeterminate_progress);
mSeekBar = view.requireViewById(R.id.volume_seekbar);
@@ -185,9 +173,8 @@ public abstract class MediaOutputBaseAdapter extends
mContainerLayout.setContentDescription(null);
mTitleText.setTextColor(mController.getColorItemContent());
mSubTitleText.setTextColor(mController.getColorItemContent());
- mSubTitleText.setSelected(true);
- mTwoLineTitleText.setTextColor(mController.getColorItemContent());
mVolumeValueText.setTextColor(mController.getColorItemContent());
+ mIconAreaLayout.setBackground(null);
mSeekBar.setProgressTintList(
ColorStateList.valueOf(mController.getColorSeekbarProgress()));
}
@@ -198,7 +185,6 @@ public abstract class MediaOutputBaseAdapter extends
void setSingleLineLayout(CharSequence title, boolean showSeekBar,
boolean showProgressBar, boolean showCheckBox, boolean showEndTouchArea) {
- mTwoLineLayout.setVisibility(View.GONE);
boolean isActive = showSeekBar || showProgressBar;
if (!mCornerAnimator.isRunning()) {
final Drawable backgroundDrawable =
@@ -216,10 +202,6 @@ public abstract class MediaOutputBaseAdapter extends
mItemLayout.setBackgroundTintList(
ColorStateList.valueOf(isActive ? mController.getColorConnectedItemBackground()
: mController.getColorItemBackground()));
- mIconAreaLayout.setBackgroundTintList(
- ColorStateList.valueOf(showSeekBar ? mController.getColorSeekbarProgress()
- : showProgressBar ? mController.getColorConnectedItemBackground()
- : mController.getColorItemBackground()));
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
mSeekBar.setAlpha(1);
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
@@ -227,7 +209,6 @@ public abstract class MediaOutputBaseAdapter extends
mSeekBar.resetVolume();
}
mTitleText.setText(title);
- mTitleText.setVisibility(View.VISIBLE);
mCheckBox.setVisibility(showCheckBox ? View.VISIBLE : View.GONE);
mEndTouchArea.setVisibility(showEndTouchArea ? View.VISIBLE : View.GONE);
ViewGroup.MarginLayoutParams params =
@@ -236,34 +217,25 @@ public abstract class MediaOutputBaseAdapter extends
: mController.getItemMarginEndDefault();
}
- void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
- boolean showProgressBar, boolean showSubtitle, boolean showStatus,
- boolean isFakeActive) {
- setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
- showStatus, false, isFakeActive);
+ void setTwoLineLayout(CharSequence title, boolean showSeekBar,
+ boolean showProgressBar, boolean showSubtitle, boolean showStatus) {
+ setTwoLineLayout(title, showSeekBar, showProgressBar, showSubtitle, showStatus, false);
}
- void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
+ void setTwoLineLayout(CharSequence title,
boolean showSeekBar, boolean showProgressBar, boolean showSubtitle,
- boolean showStatus , boolean showEndTouchArea, boolean isFakeActive) {
- mTitleText.setVisibility(View.GONE);
- mTwoLineLayout.setVisibility(View.VISIBLE);
+ boolean showStatus , boolean showEndTouchArea) {
mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
mSeekBar.setAlpha(1);
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
final Drawable backgroundDrawable;
backgroundDrawable = mContext.getDrawable(
- showSeekBar || isFakeActive ? R.drawable.media_output_item_background_active
+ showSeekBar ? R.drawable.media_output_item_background_active
: R.drawable.media_output_item_background).mutate();
mItemLayout.setBackgroundTintList(ColorStateList.valueOf(
- showSeekBar || isFakeActive ? mController.getColorConnectedItemBackground()
+ showSeekBar ? mController.getColorConnectedItemBackground()
: mController.getColorItemBackground()
));
- mIconAreaLayout.setBackgroundTintList(
- ColorStateList.valueOf(showProgressBar || isFakeActive
- ? mController.getColorConnectedItemBackground()
- : showSeekBar ? mController.getColorSeekbarProgress()
- : mController.getColorItemBackground()));
if (showSeekBar) {
updateSeekbarProgressBackground();
}
@@ -277,12 +249,7 @@ public abstract class MediaOutputBaseAdapter extends
mItemLayout.setBackground(backgroundDrawable);
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
mSubTitleText.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
- mTwoLineTitleText.setTranslationY(0);
- mTwoLineTitleText.setText(device == null ? title : getItemTitle(device));
- mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
- bFocused ? com.android.internal.R.string.config_headlineFontFamilyMedium
- : com.android.internal.R.string.config_headlineFontFamily),
- Typeface.NORMAL));
+ mTitleText.setText(title);
}
void updateSeekbarProgressBackground() {
@@ -320,10 +287,7 @@ public abstract class MediaOutputBaseAdapter extends
}
} else {
if (!mVolumeAnimator.isStarted()) {
- int percentage =
- (int) ((double) currentVolume * VOLUME_PERCENTAGE_SCALE_SIZE
- / (double) mSeekBar.getMax());
- if (percentage == 0) {
+ if (currentVolume == 0) {
updateMutedVolumeIcon(device);
} else {
updateUnmutedVolumeIcon(device);
@@ -350,20 +314,20 @@ public abstract class MediaOutputBaseAdapter extends
if (device == null || !fromUser) {
return;
}
- int progressToVolume = MediaOutputSeekbar.scaleProgressToVolume(progress);
- int deviceVolume = device.getCurrentVolume();
- int percentage =
- (int) ((double) progressToVolume * VOLUME_PERCENTAGE_SCALE_SIZE
- / (double) seekBar.getMax());
- mVolumeValueText.setText(mContext.getResources().getString(
- R.string.media_output_dialog_volume_percentage, percentage));
+
+ final String percentageString = mContext.getResources().getString(
+ R.string.media_output_dialog_volume_percentage,
+ mSeekBar.getPercentage());
+ mVolumeValueText.setText(percentageString);
+
if (mStartFromMute) {
updateUnmutedVolumeIcon(device);
mStartFromMute = false;
}
- if (progressToVolume != deviceVolume) {
- mLatestUpdateVolume = progressToVolume;
- mController.adjustVolume(device, progressToVolume);
+ int seekBarVolume = MediaOutputSeekbar.scaleProgressToVolume(progress);
+ if (seekBarVolume != device.getCurrentVolume()) {
+ mLatestUpdateVolume = seekBarVolume;
+ mController.adjustVolume(device, seekBarVolume);
}
}
@@ -443,8 +407,7 @@ public abstract class MediaOutputBaseAdapter extends
mItemLayout.setBackground(backgroundDrawable);
mItemLayout.setBackgroundTintList(
ColorStateList.valueOf(mController.getColorConnectedItemBackground()));
- mIconAreaLayout.setBackgroundTintList(
- ColorStateList.valueOf(mController.getColorConnectedItemBackground()));
+ mIconAreaLayout.setBackground(null);
}
private void initAnimator() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java
index be5d60799f79..b7381dafcf12 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java
@@ -16,22 +16,62 @@
package com.android.systemui.media.dialog;
+import android.annotation.Nullable;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.SeekBar;
+import com.android.systemui.res.R;
+
/**
* Customized SeekBar for MediaOutputDialog, apply scale between device volume and progress, to make
* adjustment smoother.
*/
public class MediaOutputSeekbar extends SeekBar {
+ // The scale is added to make slider value change smooth.
private static final int SCALE_SIZE = 1000;
- private static final int INITIAL_PROGRESS = 500;
- public static final int VOLUME_PERCENTAGE_SCALE_SIZE = 100000;
+
+ @Nullable
+ private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = null;
public MediaOutputSeekbar(Context context, AttributeSet attrs) {
super(context, attrs);
setMin(0);
+ super.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ final String percentageString = context.getResources().getString(
+ R.string.media_output_dialog_volume_percentage,
+ getPercentage());
+ // Override the default TTS for the seekbar. The percentage should correspond to
+ // the volume value, not the progress value. I.e. for the volume range 0 - 25, the
+ // percentage should be 0%, 4%, 8%, etc. It should never be 6% since 6% doesn't map
+ // to an integer volume value.
+ setStateDescription(percentageString);
+ if (mOnSeekBarChangeListener != null) {
+ mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ if (mOnSeekBarChangeListener != null) {
+ mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ if (mOnSeekBarChangeListener != null) {
+ mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setOnSeekBarChangeListener(@Nullable SeekBar.OnSeekBarChangeListener listener) {
+ mOnSeekBarChangeListener = listener;
}
static int scaleProgressToVolume(int progress) {
@@ -39,11 +79,11 @@ public class MediaOutputSeekbar extends SeekBar {
}
static int scaleVolumeToProgress(int volume) {
- return volume == 0 ? 0 : INITIAL_PROGRESS + volume * SCALE_SIZE;
+ return volume * SCALE_SIZE;
}
int getVolume() {
- return getProgress() / SCALE_SIZE;
+ return scaleProgressToVolume(getProgress());
}
void setVolume(int volume) {
@@ -51,10 +91,18 @@ public class MediaOutputSeekbar extends SeekBar {
}
void setMaxVolume(int maxVolume) {
- setMax(maxVolume * SCALE_SIZE);
+ setMax(scaleVolumeToProgress(maxVolume));
}
void resetVolume() {
setProgress(getMin());
}
+
+ int getPercentage() {
+ // The progress -> volume -> progress conversion is necessary to ensure that progress
+ // strictly corresponds to an integer volume value.
+ // Example: 10424 (progress) -> 10 (volume) -> 10000 (progress).
+ int normalizedProgress = scaleVolumeToProgress(scaleProgressToVolume(getProgress()));
+ return (int) ((double) normalizedProgress * 100 / getMax());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt
index 7d3094827e17..ea0f63ca9721 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt
@@ -40,7 +40,6 @@ import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -49,7 +48,6 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
class MediaProjectionManagerRepository
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractor.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractor.kt
index ccc54f18d419..dca0f620463c 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/taskswitcher/domain/interactor/TaskSwitchInteractor.kt
@@ -26,14 +26,12 @@ import com.android.systemui.mediaprojection.data.repository.MediaProjectionRepos
import com.android.systemui.mediaprojection.taskswitcher.data.repository.TasksRepository
import com.android.systemui.mediaprojection.taskswitcher.domain.model.TaskSwitchState
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
/** Interactor with logic related to task switching in the context of media projection. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class TaskSwitchInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
index 67fe0e981b09..1a5e605c96f8 100644
--- a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
+++ b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
@@ -79,7 +79,8 @@ public class SysUiState implements Dumpable {
/** Methods to this call can be chained together before calling {@link #commitUpdate(int)}. */
public SysUiState setFlag(@SystemUiStateFlags long flag, boolean enabled) {
- final Boolean overrideOrNull = mSceneContainerPlugin.flagValueOverride(flag);
+ final Boolean overrideOrNull = mSceneContainerPlugin != null
+ ? mSceneContainerPlugin.flagValueOverride(flag) : null;
if (overrideOrNull != null && enabled != overrideOrNull) {
if (DEBUG) {
Log.d(TAG, "setFlag for flag " + flag + " and value " + enabled + " overridden to "
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 0de8c40bddaa..1807847e3f3c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -77,7 +77,7 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.Flags;
@@ -115,7 +115,7 @@ public final class NavBarHelper implements
AccessibilityButtonModeObserver.ModeChangedListener,
AccessibilityButtonTargetsObserver.TargetsChangedListener,
AccessibilityGestureTargetsObserver.TargetsChangedListener,
- OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
+ LauncherProxyService.LauncherProxyListener, NavigationModeController.ModeChangedListener,
Dumpable, CommandQueue.Callbacks, ConfigurationController.ConfigurationListener {
private static final String TAG = NavBarHelper.class.getSimpleName();
@@ -199,7 +199,7 @@ public final class NavBarHelper implements
AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver,
AccessibilityGestureTargetsObserver accessibilityGestureTargetsObserver,
SystemActions systemActions,
- OverviewProxyService overviewProxyService,
+ LauncherProxyService launcherProxyService,
Lazy<AssistManager> assistManagerLazy,
Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
KeyguardStateController keyguardStateController,
@@ -240,7 +240,7 @@ public final class NavBarHelper implements
mNavBarMode = navigationModeController.addListener(this);
mCommandQueue.addCallback(this);
configurationController.addCallback(this);
- overviewProxyService.addCallback(this);
+ launcherProxyService.addCallback(this);
dumpManager.registerDumpable(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
index 645bd0b4b441..ebda3765cf90 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
@@ -52,7 +52,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.views.NavigationBar;
import com.android.systemui.navigationbar.views.NavigationBarView;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.shared.statusbar.phone.BarTransitions.TransitionMode;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -115,7 +115,7 @@ public class NavigationBarControllerImpl implements
@Inject
public NavigationBarControllerImpl(Context context,
- OverviewProxyService overviewProxyService,
+ LauncherProxyService launcherProxyService,
NavigationModeController navigationModeController,
SysUiState sysUiFlagsContainer,
CommandQueue commandQueue,
@@ -145,7 +145,7 @@ public class NavigationBarControllerImpl implements
mNavMode = navigationModeController.addListener(this);
mNavBarHelper = navBarHelper;
mTaskbarDelegate = taskbarDelegate;
- mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService,
+ mTaskbarDelegate.setDependencies(commandQueue, launcherProxyService,
navBarHelper, navigationModeController, sysUiFlagsContainer,
dumpManager, autoHideControllerStore.forDisplay(mContext.getDisplayId()),
lightBarController, pipOptional, backAnimation.orElse(null),
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index c2dacd6690a0..9d8943052b38 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -17,9 +17,9 @@
package com.android.systemui.navigationbar;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_VISIBLE;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
+import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -30,16 +30,16 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISMISS_IME;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_ALT_BACK;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import android.app.StatusBarManager;
-import android.app.StatusBarManager.NavigationHint;
+import android.app.StatusBarManager.NavbarFlags;
import android.app.StatusBarManager.WindowVisibleState;
import android.content.Context;
import android.graphics.Rect;
@@ -70,7 +70,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.model.SysUiState;
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.LauncherProxyService;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.statusbar.phone.BarTransitions;
@@ -96,7 +96,7 @@ import javax.inject.Inject;
/** */
@SysUISingleton
public class TaskbarDelegate implements CommandQueue.Callbacks,
- OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
+ LauncherProxyService.LauncherProxyListener, NavigationModeController.ModeChangedListener,
Dumpable {
private static final String TAG = TaskbarDelegate.class.getSimpleName();
@@ -104,7 +104,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private final LightBarTransitionsController.Factory mLightBarTransitionsControllerFactory;
private boolean mInitialized;
private CommandQueue mCommandQueue;
- private OverviewProxyService mOverviewProxyService;
+ private LauncherProxyService mLauncherProxyService;
private NavBarHelper mNavBarHelper;
private NavigationModeController mNavigationModeController;
private SysUiState mSysUiState;
@@ -114,8 +114,8 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private TaskStackChangeListeners mTaskStackChangeListeners;
private Optional<Pip> mPipOptional;
private int mDefaultDisplayId;
- @NavigationHint
- private int mNavigationIconHints;
+ @NavbarFlags
+ private int mNavbarFlags;
private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater =
new NavBarHelper.NavbarTaskbarStateUpdater() {
@Override
@@ -210,7 +210,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
}
public void setDependencies(CommandQueue commandQueue,
- OverviewProxyService overviewProxyService,
+ LauncherProxyService launcherProxyService,
NavBarHelper navBarHelper,
NavigationModeController navigationModeController,
SysUiState sysUiState, DumpManager dumpManager,
@@ -222,7 +222,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
DisplayTracker displayTracker) {
// TODO: adding this in the ctor results in a dagger dependency cycle :(
mCommandQueue = commandQueue;
- mOverviewProxyService = overviewProxyService;
+ mLauncherProxyService = launcherProxyService;
mNavBarHelper = navBarHelper;
mNavigationModeController = navigationModeController;
mSysUiState = sysUiState;
@@ -240,12 +240,12 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void onDisplayReady(int displayId) {
CommandQueue.Callbacks.super.onDisplayReady(displayId);
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().onDisplayReady(displayId);
+ mLauncherProxyService.getProxy().onDisplayReady(displayId);
} catch (RemoteException e) {
Log.e(TAG, "onDisplayReady() failed", e);
}
@@ -254,12 +254,12 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void onDisplayRemoved(int displayId) {
CommandQueue.Callbacks.super.onDisplayRemoved(displayId);
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().onDisplayRemoved(displayId);
+ mLauncherProxyService.getProxy().onDisplayRemoved(displayId);
} catch (RemoteException e) {
Log.e(TAG, "onDisplayRemoved() failed", e);
}
@@ -268,12 +268,12 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void onDisplayRemoveSystemDecorations(int displayId) {
CommandQueue.Callbacks.super.onDisplayRemoveSystemDecorations(displayId);
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().onDisplayRemoveSystemDecorations(displayId);
+ mLauncherProxyService.getProxy().onDisplayRemoveSystemDecorations(displayId);
} catch (RemoteException e) {
Log.e(TAG, "onDisplaySystemDecorationsRemoved() failed", e);
}
@@ -287,7 +287,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void applyDarkIntensity(float darkIntensity) {
mBgHandler.post(() -> {
- mOverviewProxyService.onNavButtonsDarkIntensityChanged(darkIntensity);
+ mLauncherProxyService.onNavButtonsDarkIntensityChanged(darkIntensity);
});
}
@@ -309,7 +309,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
mDefaultDisplayId = displayId;
parseCurrentSysuiState();
mCommandQueue.addCallback(this);
- mOverviewProxyService.addCallback(this);
+ mLauncherProxyService.addCallback(this);
onNavigationModeChanged(mNavigationModeController.addListener(this));
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
// Initialize component callback
@@ -334,7 +334,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
return;
}
mCommandQueue.removeCallback(this);
- mOverviewProxyService.removeCallback(this);
+ mLauncherProxyService.removeCallback(this);
mNavigationModeController.removeListener(this);
mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
mScreenPinningNotify = null;
@@ -379,11 +379,11 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
mSysUiState.setFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE, clickable)
.setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable)
.setFlag(SYSUI_STATE_IME_VISIBLE,
- (mNavigationIconHints & NAVIGATION_HINT_IME_VISIBLE) != 0)
+ (mNavbarFlags & NAVBAR_IME_VISIBLE) != 0)
.setFlag(SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE,
- (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0)
- .setFlag(SYSUI_STATE_IME_ALT_BACK,
- (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0)
+ (mNavbarFlags & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0)
+ .setFlag(SYSUI_STATE_BACK_DISMISS_IME,
+ (mNavbarFlags & NAVBAR_BACK_DISMISS_IME) != 0)
.setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
(mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
.setFlag(SYSUI_STATE_HOME_DISABLED,
@@ -401,43 +401,43 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
}
void onTransitionModeUpdated(int barMode, boolean checkBarModes) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().onTransitionModeUpdated(barMode, checkBarModes);
+ mLauncherProxyService.getProxy().onTransitionModeUpdated(barMode, checkBarModes);
} catch (RemoteException e) {
Log.e(TAG, "onTransitionModeUpdated() failed, barMode: " + barMode, e);
}
}
void checkNavBarModes(int displayId) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().checkNavBarModes(displayId);
+ mLauncherProxyService.getProxy().checkNavBarModes(displayId);
} catch (RemoteException e) {
Log.e(TAG, "checkNavBarModes() failed", e);
}
}
void finishBarAnimations(int displayId) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().finishBarAnimations(displayId);
+ mLauncherProxyService.getProxy().finishBarAnimations(displayId);
} catch (RemoteException e) {
Log.e(TAG, "finishBarAnimations() failed", e);
}
}
void touchAutoDim(int displayId) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
@@ -445,31 +445,31 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
int state = mStatusBarStateController.getState();
boolean shouldReset =
state != StatusBarState.KEYGUARD && state != StatusBarState.SHADE_LOCKED;
- mOverviewProxyService.getProxy().touchAutoDim(displayId, shouldReset);
+ mLauncherProxyService.getProxy().touchAutoDim(displayId, shouldReset);
} catch (RemoteException e) {
Log.e(TAG, "touchAutoDim() failed", e);
}
}
void transitionTo(int displayId, @BarTransitions.TransitionMode int barMode, boolean animate) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().transitionTo(displayId, barMode, animate);
+ mLauncherProxyService.getProxy().transitionTo(displayId, barMode, animate);
} catch (RemoteException e) {
Log.e(TAG, "transitionTo() failed, barMode: " + barMode, e);
}
}
private void updateAssistantAvailability(boolean assistantAvailable,
boolean longPressHomeEnabled) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable,
+ mLauncherProxyService.getProxy().onAssistantAvailable(assistantAvailable,
longPressHomeEnabled);
} catch (RemoteException e) {
Log.e(TAG, "onAssistantAvailable() failed, available: " + assistantAvailable, e);
@@ -477,24 +477,24 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
}
private void updateWallpaperVisible(int displayId, boolean visible) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().updateWallpaperVisibility(displayId, visible);
+ mLauncherProxyService.getProxy().updateWallpaperVisibility(displayId, visible);
} catch (RemoteException e) {
Log.e(TAG, "updateWallpaperVisibility() failed, visible: " + visible, e);
}
}
private void appTransitionPending(boolean pending) {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().appTransitionPending(pending);
+ mLauncherProxyService.getProxy().appTransitionPending(pending);
} catch (RemoteException e) {
Log.e(TAG, "appTransitionPending() failed, pending: " + pending, e);
}
@@ -506,13 +506,13 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
// Count imperceptible changes as visible so we transition taskbar out quickly.
final boolean isImeVisible = mNavBarHelper.isImeVisible(vis)
|| (vis & InputMethodService.IME_VISIBLE_IMPERCEPTIBLE) != 0;
- final int hints = Utilities.calculateNavigationIconHints(mNavigationIconHints,
- backDisposition, isImeVisible, showImeSwitcher);
- if (hints == mNavigationIconHints) {
+ final int flags = Utilities.updateNavbarFlagsFromIme(mNavbarFlags, backDisposition,
+ isImeVisible, showImeSwitcher);
+ if (flags == mNavbarFlags) {
return;
}
- mNavigationIconHints = hints;
+ mNavbarFlags = flags;
updateSysuiFlags();
}
@@ -528,14 +528,14 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void onRotationProposal(int rotation, boolean isValid) {
- mOverviewProxyService.onRotationProposal(rotation, isValid);
+ mLauncherProxyService.onRotationProposal(rotation, isValid);
}
@Override
public void disable(int displayId, int state1, int state2, boolean animate) {
mDisabledFlags = state1;
updateSysuiFlags();
- mOverviewProxyService.disable(displayId, state1, state2, animate);
+ mLauncherProxyService.disable(displayId, state1, state2, animate);
}
@Override
@@ -543,7 +543,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, int behavior,
@InsetsType int requestedVisibleTypes, String packageName,
LetterboxDetails[] letterboxDetails) {
- mOverviewProxyService.onSystemBarAttributesChanged(displayId, behavior);
+ mLauncherProxyService.onSystemBarAttributesChanged(displayId, behavior);
boolean nbModeChanged = false;
if (mAppearance != appearance) {
mAppearance = appearance;
@@ -596,12 +596,12 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void toggleTaskbar() {
- if (mOverviewProxyService.getProxy() == null) {
+ if (mLauncherProxyService.getProxy() == null) {
return;
}
try {
- mOverviewProxyService.getProxy().onTaskbarToggled();
+ mLauncherProxyService.getProxy().onTaskbarToggled();
} catch (RemoteException e) {
Log.e(TAG, "onTaskbarToggled() failed", e);
}
@@ -673,7 +673,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {
- mOverviewProxyService.onNavigationBarLumaSamplingEnabled(displayId, enable);
+ mLauncherProxyService.onNavigationBarLumaSamplingEnabled(displayId, enable);
}
@Override
@@ -707,7 +707,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("TaskbarDelegate (mDefaultDisplayId=" + mDefaultDisplayId + "):");
- pw.println(" mNavigationIconHints=" + mNavigationIconHints);
+ pw.println(" mNavbarFlags=" + mNavbarFlags);
pw.println(" mNavigationMode=" + mNavigationMode);
pw.println(" mDisabledFlags=" + mDisabledFlags);
pw.println(" mTaskBarWindowState=" + mTaskBarWindowState);
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 1c94f56f0942..f44c2c01951c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -85,7 +85,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.NavigationEdgeBackPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -155,8 +155,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
}
};
- private OverviewProxyService.OverviewProxyListener mQuickSwitchListener =
- new OverviewProxyService.OverviewProxyListener() {
+ private LauncherProxyService.LauncherProxyListener mQuickSwitchListener =
+ new LauncherProxyService.LauncherProxyListener() {
@Override
public void onPrioritizedRotation(@Surface.Rotation int rotation) {
mStartingQuickstepRotation = rotation;
@@ -197,7 +197,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private final Context mContext;
private final UserTracker mUserTracker;
- private final OverviewProxyService mOverviewProxyService;
+ private final LauncherProxyService mLauncherProxyService;
private final SysUiState mSysUiState;
private Runnable mStateChangeCallback;
private Consumer<Boolean> mButtonForcedVisibleCallback;
@@ -332,7 +332,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
: SysUiStatsLog.BACK_GESTURE__TYPE__COMPLETED);
if (!mInRejectedExclusion) {
// Log successful back gesture to contextual edu stats
- mOverviewProxyService.updateContextualEduStats(mIsTrackpadThreeFingerSwipe,
+ mLauncherProxyService.updateContextualEduStats(mIsTrackpadThreeFingerSwipe,
GestureType.BACK);
}
}
@@ -441,7 +441,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
@AssistedInject
EdgeBackGestureHandler(
@Assisted Context context,
- OverviewProxyService overviewProxyService,
+ LauncherProxyService launcherProxyService,
SysUiState sysUiState,
PluginManager pluginManager,
@BackPanelUiThread UiThreadContext uiThreadContext,
@@ -468,7 +468,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mBackgroundExecutor = backgroundExecutor;
mBgHandler = bgHandler;
mUserTracker = userTracker;
- mOverviewProxyService = overviewProxyService;
+ mLauncherProxyService = launcherProxyService;
mSysUiState = sysUiState;
mPluginManager = pluginManager;
mNavigationModeController = navigationModeController;
@@ -620,7 +620,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
*/
public void onNavBarAttached() {
mIsAttached = true;
- mOverviewProxyService.addCallback(mQuickSwitchListener);
+ mLauncherProxyService.addCallback(mQuickSwitchListener);
mSysUiState.addCallback(mSysUiStateCallback);
mInputManager.registerInputDeviceListener(mInputDeviceListener, mBgHandler);
int[] inputDevices = mInputManager.getInputDeviceIds();
@@ -636,7 +636,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
*/
public void onNavBarDetached() {
mIsAttached = false;
- mOverviewProxyService.removeCallback(mQuickSwitchListener);
+ mLauncherProxyService.removeCallback(mQuickSwitchListener);
mSysUiState.removeCallback(mSysUiStateCallback);
mInputManager.unregisterInputDeviceListener(mInputDeviceListener);
mTrackpadsConnected.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
index 2744f9f84ccf..f95f45906b23 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
@@ -17,14 +17,14 @@
package com.android.systemui.navigationbar.views;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_VISIBLE;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
+import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
-import static android.app.StatusBarManager.navigationHintsToString;
+import static android.app.StatusBarManager.navbarFlagsToString;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.view.InsetsSource.FLAG_SUPPRESS_SCRIM;
@@ -36,7 +36,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
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.recents.LauncherProxyService.LauncherProxyListener;
import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
import static com.android.systemui.shared.rotation.RotationButtonController.DEBUG_ROTATION;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -44,9 +44,9 @@ import static com.android.systemui.shared.statusbar.phone.BarTransitions.Transit
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_ALT_BACK;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISMISS_IME;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode;
@@ -59,7 +59,7 @@ import android.annotation.NonNull;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.StatusBarManager;
-import android.app.StatusBarManager.NavigationHint;
+import android.app.StatusBarManager.NavbarFlags;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
@@ -131,7 +131,7 @@ import com.android.systemui.navigationbar.views.buttons.KeyButtonView;
import com.android.systemui.navigationbar.views.buttons.NavBarButtonClickLogger;
import com.android.systemui.navigationbar.views.buttons.NavbarOrientationTrackingLogger;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.res.R;
import com.android.systemui.settings.DisplayTracker;
@@ -212,7 +212,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private final ShadeViewController mShadeViewController;
private final PanelExpansionInteractor mPanelExpansionInteractor;
private final NotificationRemoteInputManager mNotificationRemoteInputManager;
- private final OverviewProxyService mOverviewProxyService;
+ private final LauncherProxyService mLauncherProxyService;
private final NavigationModeController mNavigationModeController;
private final UserTracker mUserTracker;
private final CommandQueue mCommandQueue;
@@ -237,8 +237,8 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
- @NavigationHint
- private int mNavigationIconHints = 0;
+ @NavbarFlags
+ private int mNavbarFlags;
private @TransitionMode int mTransitionMode;
private boolean mLongPressHomeEnabled;
@@ -283,7 +283,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
* gesture to indicate to them that they can continue in that orientation without having to
* rotate the phone
* The secondary handle will show when we get
- * {@link OverviewProxyListener#notifyPrioritizedRotation(int)} callback with the
+ * {@link LauncherProxyListener#notifyPrioritizedRotation(int)} callback with the
* original handle hidden and we'll flip the visibilities once the
* {@link #mTasksFrozenListener} fires
*/
@@ -387,12 +387,12 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
}
};
- private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
+ private final LauncherProxyListener mLauncherProxyListener = new LauncherProxyListener() {
@Override
public void onConnectionChanged(boolean isConnected) {
- mView.onOverviewProxyConnectionChange(
- mOverviewProxyService.isEnabled());
- mView.setShouldShowSwipeUpUi(mOverviewProxyService.shouldShowSwipeUpUI());
+ mView.onLauncherProxyConnectionChange(
+ mLauncherProxyService.isEnabled());
+ mView.setShouldShowSwipeUpUi(mLauncherProxyService.shouldShowSwipeUpUI());
updateScreenPinningGestures();
}
@@ -565,7 +565,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
AccessibilityManager accessibilityManager,
DeviceProvisionedController deviceProvisionedController,
MetricsLogger metricsLogger,
- OverviewProxyService overviewProxyService,
+ LauncherProxyService launcherProxyService,
NavigationModeController navigationModeController,
StatusBarStateController statusBarStateController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
@@ -618,7 +618,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mShadeViewController = shadeViewController;
mPanelExpansionInteractor = panelExpansionInteractor;
mNotificationRemoteInputManager = notificationRemoteInputManager;
- mOverviewProxyService = overviewProxyService;
+ mLauncherProxyService = launcherProxyService;
mNavigationModeController = navigationModeController;
mUserTracker = userTracker;
mCommandQueue = commandQueue;
@@ -827,7 +827,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
setNavBarMode(mNavBarMode);
repositionNavigationBar(mCurrentRotation);
mView.setUpdateActiveTouchRegionsCallback(
- () -> mOverviewProxyService.onActiveNavBarRegionChanges(
+ () -> mLauncherProxyService.onActiveNavBarRegionChanges(
getButtonLocations(true /* inScreen */, true /* useNearestRegion */)));
mView.getViewTreeObserver().addOnComputeInternalInsetsListener(
@@ -843,7 +843,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
notifyNavigationBarScreenOn();
- mOverviewProxyService.addCallback(mOverviewProxyListener);
+ mLauncherProxyService.addCallback(mLauncherProxyListener);
updateSystemUiStateFlags();
// Currently there is no accelerometer sensor on non-default display.
@@ -881,7 +881,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
public void onViewDetached() {
mView.setUpdateActiveTouchRegionsCallback(null);
getBarTransitions().destroy();
- mOverviewProxyService.removeCallback(mOverviewProxyListener);
+ mLauncherProxyService.removeCallback(mLauncherProxyListener);
mUserTracker.removeCallback(mUserChangedCallback);
mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
if (mOrientationHandle != null) {
@@ -1115,7 +1115,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled);
pw.println(" mNavigationBarWindowState="
+ windowStateToString(mNavigationBarWindowState));
- pw.println(" mNavigationIconHints=" + navigationHintsToString(mNavigationIconHints));
+ pw.println(" mNavbarFlags=" + navbarFlagsToString(mNavbarFlags));
pw.println(" mTransitionMode="
+ BarTransitions.modeToString(mTransitionMode));
pw.println(" mTransientShown=" + mTransientShown);
@@ -1141,13 +1141,13 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
return;
}
final boolean isImeVisible = mNavBarHelper.isImeVisible(vis);
- final int hints = Utilities.calculateNavigationIconHints(mNavigationIconHints,
- backDisposition, isImeVisible, showImeSwitcher);
- if (hints == mNavigationIconHints) {
+ final int flags = Utilities.updateNavbarFlagsFromIme(mNavbarFlags, backDisposition,
+ isImeVisible, showImeSwitcher);
+ if (flags == mNavbarFlags) {
return;
}
- setNavigationIconHints(hints);
+ setNavbarFlags(flags);
checkBarModes();
updateSystemUiStateFlags();
}
@@ -1687,11 +1687,11 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
.setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable)
.setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isNavBarWindowVisible())
.setFlag(SYSUI_STATE_IME_VISIBLE,
- (mNavigationIconHints & NAVIGATION_HINT_IME_VISIBLE) != 0)
+ (mNavbarFlags & NAVBAR_IME_VISIBLE) != 0)
.setFlag(SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE,
- (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0)
- .setFlag(SYSUI_STATE_IME_ALT_BACK,
- (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0)
+ (mNavbarFlags & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0)
+ .setFlag(SYSUI_STATE_BACK_DISMISS_IME,
+ (mNavbarFlags & NAVBAR_BACK_DISMISS_IME) != 0)
.setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
allowSystemGestureIgnoringBarVisibility())
.commitUpdate(mDisplayId);
@@ -1699,9 +1699,9 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private void updateAssistantEntrypoints(boolean assistantAvailable,
boolean longPressHomeEnabled) {
- if (mOverviewProxyService.getProxy() != null) {
+ if (mLauncherProxyService.getProxy() != null) {
try {
- mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable,
+ mLauncherProxyService.getProxy().onAssistantAvailable(assistantAvailable,
longPressHomeEnabled);
} catch (RemoteException e) {
Log.w(TAG, "Unable to send assistant availability data to launcher");
@@ -1934,37 +1934,37 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
};
@VisibleForTesting
- @NavigationHint
- int getNavigationIconHints() {
- return mNavigationIconHints;
+ @NavbarFlags
+ int getNavbarFlags() {
+ return mNavbarFlags;
}
/**
- * Updates the navigation icons based on {@code hints}.
+ * Sets the navigation bar state flags.
*
- * @param hints bit flags defined in {@link StatusBarManager}.
+ * @param flags the navigation bar state flags.
*/
- private void setNavigationIconHints(@NavigationHint int hints) {
- if (hints == mNavigationIconHints) {
+ private void setNavbarFlags(@NavbarFlags int flags) {
+ if (flags == mNavbarFlags) {
return;
}
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 =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
- if (newBackAlt != oldBackAlt) {
- mView.onBackAltChanged(newBackAlt);
+ final boolean backDismissIme = (flags & StatusBarManager.NAVBAR_BACK_DISMISS_IME) != 0;
+ final boolean oldBackDismissIme =
+ (mNavbarFlags & StatusBarManager.NAVBAR_BACK_DISMISS_IME) != 0;
+ if (backDismissIme != oldBackDismissIme) {
+ mView.onBackDismissImeChanged(backDismissIme);
}
- mImeVisible = (hints & NAVIGATION_HINT_IME_VISIBLE) != 0;
+ mImeVisible = (flags & NAVBAR_IME_VISIBLE) != 0;
- mView.setNavigationIconHints(hints);
+ mView.setNavbarFlags(flags);
}
if (DEBUG) {
- android.widget.Toast.makeText(mContext, "Navigation icon hints = " + hints, 500)
+ android.widget.Toast.makeText(mContext, "Navbar flags = " + flags, 500)
.show();
}
- mNavigationIconHints = hints;
+ mNavbarFlags = flags;
}
/**
@@ -2108,7 +2108,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
if (!canShowSecondaryHandle()) {
resetSecondaryHandle();
}
- mView.setShouldShowSwipeUpUi(mOverviewProxyService.shouldShowSwipeUpUI());
+ mView.setShouldShowSwipeUpUi(mLauncherProxyService.shouldShowSwipeUpUI());
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java
index 96b730c08397..2c5a9c84645b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java
@@ -41,7 +41,7 @@ import com.android.systemui.navigationbar.views.buttons.ButtonDispatcher;
import com.android.systemui.navigationbar.views.buttons.KeyButtonView;
import com.android.systemui.navigationbar.views.buttons.ReverseLinearLayout;
import com.android.systemui.navigationbar.views.buttons.ReverseLinearLayout.ReverseRelativeLayout;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.res.R;
import com.android.systemui.shared.system.QuickStepContract;
@@ -117,13 +117,13 @@ public class NavigationBarInflaterView extends FrameLayout {
private boolean mIsVertical;
private boolean mAlternativeOrder;
- private OverviewProxyService mOverviewProxyService;
+ private LauncherProxyService mLauncherProxyService;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
createInflaters();
- mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+ mLauncherProxyService = Dependency.get(LauncherProxyService.class);
mListener = new Listener(this);
mNavBarMode = Dependency.get(NavigationModeController.class).addListener(mListener);
}
@@ -159,7 +159,7 @@ public class NavigationBarInflaterView extends FrameLayout {
protected String getDefaultLayout() {
final int defaultResource = QuickStepContract.isGesturalMode(mNavBarMode)
? R.string.config_navBarLayoutHandle
- : mOverviewProxyService.shouldShowSwipeUpUI()
+ : mLauncherProxyService.shouldShowSwipeUpUI()
? R.string.config_navBarLayoutQuickstep
: R.string.config_navBarLayout;
return getContext().getString(defaultResource);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
index de61d404b1e8..36cb8fa374b0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
@@ -16,9 +16,9 @@
package com.android.systemui.navigationbar.views;
-import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_VISIBLE;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
+import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
+import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
import static android.inputmethodservice.InputMethodService.canImeRenderGesturalNavButtons;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -34,7 +34,7 @@ import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.DrawableRes;
-import android.app.StatusBarManager.NavigationHint;
+import android.app.StatusBarManager.NavbarFlags;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
@@ -116,8 +116,8 @@ public class NavigationBarView extends FrameLayout {
boolean mLongClickableAccessibilityButton;
int mDisabledFlags = 0;
- @NavigationHint
- int mNavigationIconHints = 0;
+ @NavbarFlags
+ private int mNavbarFlags;
private int mNavBarMode;
private boolean mImeDrawsImeNavBar;
@@ -180,7 +180,7 @@ public class NavigationBarView extends FrameLayout {
*/
private final boolean mImeCanRenderGesturalNavButtons = canImeRenderGesturalNavButtons();
private Gefingerpoken mTouchHandler;
- private boolean mOverviewProxyEnabled;
+ private boolean mLauncherProxyEnabled;
private boolean mShowSwipeUpUi;
private UpdateActiveTouchRegionsCallback mUpdateActiveTouchRegionsCallback;
@@ -214,7 +214,11 @@ public class NavigationBarView extends FrameLayout {
}
}
- public void onBackAltCleared() {
+ /**
+ * Called when the back button is no longer visually adjusted to indicate that it will
+ * dismiss the IME when pressed.
+ */
+ public void onBackDismissImeCleared() {
ButtonDispatcher backButton = getBackButton();
// When dismissing ime during unlock, force the back button to run the same appearance
@@ -503,9 +507,9 @@ public class NavigationBarView extends FrameLayout {
}
private void orientBackButton(KeyButtonDrawable drawable) {
- final boolean useAltBack = (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0;
+ final boolean isBackDismissIme = (mNavbarFlags & NAVBAR_BACK_DISMISS_IME) != 0;
final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
+ float degrees = isBackDismissIme ? (isRtl ? 90 : -90) : 0;
if (drawable.getRotation() == degrees) {
return;
}
@@ -517,7 +521,7 @@ public class NavigationBarView extends FrameLayout {
// Animate the back button's rotation to the new degrees and only in portrait move up the
// back button to line up with the other buttons
- float targetY = !mShowSwipeUpUi && !mIsVertical && useAltBack
+ float targetY = !mShowSwipeUpUi && !mIsVertical && isBackDismissIme
? - getResources().getDimension(R.dimen.navbar_back_button_ime_offset)
: 0;
ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable,
@@ -558,24 +562,25 @@ public class NavigationBarView extends FrameLayout {
super.setLayoutDirection(layoutDirection);
}
- void setNavigationIconHints(@NavigationHint int hints) {
- if (hints == mNavigationIconHints) {
+ void setNavbarFlags(@NavbarFlags int flags) {
+ if (flags == mNavbarFlags) {
return;
}
- mNavigationIconHints = hints;
+ mNavbarFlags = flags;
updateNavButtonIcons();
}
/**
- * Called when the boolean value of whether to adjust the back button for the IME changed.
+ * Called when the state of the back button being visually adjusted to indicate that it will
+ * dismiss the IME when pressed has changed.
*
- * @param useBackAlt whether to adjust the back button for the IME.
+ * @param isBackDismissIme whether the back button is adjusted for IME dismissal.
*
* @see android.inputmethodservice.InputMethodService.BackDispositionMode
*/
- void onBackAltChanged(boolean useBackAlt) {
- if (!useBackAlt) {
- mTransitionListener.onBackAltCleared();
+ void onBackDismissImeChanged(boolean isBackDismissIme) {
+ if (!isBackDismissIme) {
+ mTransitionListener.onBackDismissImeCleared();
}
}
@@ -599,7 +604,7 @@ public class NavigationBarView extends FrameLayout {
// We have to replace or restore the back and home button icons when exiting or entering
// carmode, respectively. Recents are not available in CarMode in nav bar so change
// to recent icon is not required.
- final boolean useAltBack = (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0;
+ final boolean isBackDismissIme = (mNavbarFlags & NAVBAR_BACK_DISMISS_IME) != 0;
KeyButtonDrawable backIcon = mBackIcon;
orientBackButton(backIcon);
KeyButtonDrawable homeIcon = mHomeDefaultIcon;
@@ -614,7 +619,7 @@ public class NavigationBarView extends FrameLayout {
// Update IME switcher button visibility, a11y and rotate button always overrides
// the appearance.
final boolean isImeSwitcherButtonVisible =
- (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_VISIBLE) != 0
+ (mNavbarFlags & NAVBAR_IME_SWITCHER_BUTTON_VISIBLE) != 0
&& !isImeRenderingNavButtons();
mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher, isImeSwitcherButtonVisible);
@@ -630,14 +635,14 @@ public class NavigationBarView extends FrameLayout {
boolean disableHomeHandle = disableRecent
&& ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
- boolean disableBack = !useAltBack && (mEdgeBackGestureHandler.isHandlingGestures()
+ boolean disableBack = !isBackDismissIme && (mEdgeBackGestureHandler.isHandlingGestures()
|| ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0))
|| isImeRenderingNavButtons();
// When screen pinning, don't hide back and home when connected service or back and
// recents buttons when disconnected from launcher service in screen pinning mode,
// as they are used for exiting.
- if (mOverviewProxyEnabled) {
+ if (mLauncherProxyEnabled) {
// Force disable recents when not in legacy mode
disableRecent |= !QuickStepContract.isLegacyMode(mNavBarMode);
if (mScreenPinningActive && !QuickStepContract.isGesturalMode(mNavBarMode)) {
@@ -668,9 +673,8 @@ public class NavigationBarView extends FrameLayout {
* Returns whether the IME is currently visible and drawing the nav buttons.
*/
boolean isImeRenderingNavButtons() {
- return mImeDrawsImeNavBar
- && mImeCanRenderGesturalNavButtons
- && (mNavigationIconHints & NAVIGATION_HINT_IME_VISIBLE) != 0;
+ return mImeDrawsImeNavBar && mImeCanRenderGesturalNavButtons
+ && (mNavbarFlags & NAVBAR_IME_VISIBLE) != 0;
}
@VisibleForTesting
@@ -760,8 +764,8 @@ public class NavigationBarView extends FrameLayout {
}
}
- void onOverviewProxyConnectionChange(boolean enabled) {
- mOverviewProxyEnabled = enabled;
+ void onLauncherProxyConnectionChange(boolean enabled) {
+ mLauncherProxyEnabled = enabled;
}
void setShouldShowSwipeUpUi(boolean showSwipeUpUi) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java
index 111a2d43f881..32a03e5b10e9 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java
@@ -61,7 +61,7 @@ import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.res.R;
import com.android.systemui.shared.navigationbar.KeyButtonRipple;
import com.android.systemui.shared.system.QuickStepContract;
@@ -82,7 +82,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
@VisibleForTesting boolean mLongClicked;
private OnClickListener mOnClickListener;
private final KeyButtonRipple mRipple;
- private final OverviewProxyService mOverviewProxyService;
+ private final LauncherProxyService mLauncherProxyService;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private final InputManagerGlobal mInputManagerGlobal;
private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
@@ -181,7 +181,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mRipple = new KeyButtonRipple(context, this, R.dimen.key_button_ripple_max_width);
- mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+ mLauncherProxyService = Dependency.get(LauncherProxyService.class);
mInputManagerGlobal = manager;
setBackground(mRipple);
setWillNotDraw(false);
@@ -282,7 +282,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
@Override
public boolean onTouchEvent(MotionEvent ev) {
- final boolean showSwipeUI = mOverviewProxyService.shouldShowSwipeUpUI();
+ final boolean showSwipeUI = mLauncherProxyService.shouldShowSwipeUpUI();
final int action = ev.getAction();
int x, y;
if (action == MotionEvent.ACTION_DOWN) {
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
index 195b0cebe2eb..1b9251061f3d 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
@@ -21,7 +21,8 @@ import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.UserActionResult.HideOverlay
-import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay.HideCurrentOverlays
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
@@ -38,7 +39,10 @@ class NotificationsShadeOverlayActionsViewModel @AssistedInject constructor() :
Swipe.Up to HideOverlay(Overlays.NotificationsShade),
Back to HideOverlay(Overlays.NotificationsShade),
Swipe.Down(fromSource = SceneContainerEdge.TopRight) to
- ReplaceByOverlay(Overlays.QuickSettingsShade),
+ ShowOverlay(
+ Overlays.QuickSettingsShade,
+ hideCurrentOverlays = HideCurrentOverlays.Some(Overlays.NotificationsShade),
+ ),
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index afb852ae824c..c8f7be6d80b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -17,7 +17,6 @@
package com.android.systemui.qs;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import static com.android.systemui.Flags.quickSettingsVisualHapticsLongpress;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -364,12 +363,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
}
private void addTile(final QSTile tile, boolean collapsedView) {
- QSLongPressEffect longPressEffect;
- if (quickSettingsVisualHapticsLongpress()) {
- longPressEffect = mLongPressEffectProvider.get();
- } else {
- longPressEffect = null;
- }
+ QSLongPressEffect longPressEffect = mLongPressEffectProvider.get();
final QSTileViewImpl tileView = new QSTileViewImpl(
getContext(), collapsedView, longPressEffect);
final TileRecord r = new TileRecord(tile, tileView);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
index 07ceb6425574..219fc2fdc5ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
@@ -81,7 +81,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.io.PrintWriter
import javax.inject.Named
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.coroutineScope
@@ -91,7 +90,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
-@OptIn(ExperimentalCoroutinesApi::class)
class QSFragmentComposeViewModel
@AssistedInject
constructor(
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 cc872060b827..9546e355dca2 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
@@ -38,14 +38,14 @@ import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
-import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.util.icuMessageFormat
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Provider
import kotlin.math.max
import kotlinx.coroutines.CoroutineStart
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -53,6 +53,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.isActive
@@ -73,7 +74,7 @@ class FooterActionsViewModel(
val settings: FooterActionsButtonViewModel,
/** The model for the power button. */
- val power: FooterActionsButtonViewModel?,
+ val power: Flow<FooterActionsButtonViewModel?>,
/**
* Observe the device monitoring dialog requests and show the dialog accordingly. This function
@@ -116,6 +117,7 @@ class FooterActionsViewModel(
@ShadeDisplayAware private val context: Context,
private val falsingManager: FalsingManager,
private val footerActionsInteractor: FooterActionsInteractor,
+ private val shadeModeInteractor: ShadeModeInteractor,
private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>,
private val activityStarter: ActivityStarter,
@Named(PM_LITE_ENABLED) private val showPowerButton: Boolean,
@@ -138,9 +140,10 @@ class FooterActionsViewModel(
)
}
- return FooterActionsViewModel(
+ return createFooterActionsViewModel(
context,
footerActionsInteractor,
+ shadeModeInteractor.shadeMode,
falsingManager,
globalActionsDialogLite,
activityStarter,
@@ -148,7 +151,6 @@ class FooterActionsViewModel(
)
}
- @OptIn(ExperimentalCoroutinesApi::class)
fun create(lifecycleCoroutineScope: LifecycleCoroutineScope): FooterActionsViewModel {
val globalActionsDialogLite = globalActionsDialogLiteProvider.get()
if (lifecycleCoroutineScope.isActive) {
@@ -163,9 +165,10 @@ class FooterActionsViewModel(
globalActionsDialogLite.destroy()
}
- return FooterActionsViewModel(
+ return createFooterActionsViewModel(
context,
footerActionsInteractor,
+ shadeModeInteractor.shadeMode,
falsingManager,
globalActionsDialogLite,
activityStarter,
@@ -175,9 +178,10 @@ class FooterActionsViewModel(
}
}
-fun FooterActionsViewModel(
+fun createFooterActionsViewModel(
@ShadeDisplayAware appContext: Context,
footerActionsInteractor: FooterActionsInteractor,
+ shadeMode: Flow<ShadeMode>,
falsingManager: FalsingManager,
globalActionsDialogLite: GlobalActionsDialogLite,
activityStarter: ActivityStarter,
@@ -272,11 +276,12 @@ fun FooterActionsViewModel(
userSwitcherViewModel(qsThemedContext, footerActionsInteractor, ::onUserSwitcherClicked)
val settings = settingsButtonViewModel(qsThemedContext, ::onSettingsButtonClicked)
+
val power =
if (showPowerButton) {
- powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked)
+ powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked, shadeMode)
} else {
- null
+ flowOf(null)
}
return FooterActionsViewModel(
@@ -403,19 +408,23 @@ fun settingsButtonViewModel(
fun powerButtonViewModel(
qsThemedContext: Context,
onPowerButtonClicked: (Expandable) -> Unit,
-): FooterActionsButtonViewModel {
- return FooterActionsButtonViewModel(
- id = R.id.pm_lite,
- Icon.Resource(
- android.R.drawable.ic_lock_power_off,
- ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
- ),
- iconTint =
- Utils.getColorAttrDefaultColor(
- qsThemedContext,
- if (DualShade.isEnabled) R.attr.onShadeInactiveVariant else R.attr.onShadeActive,
+ shadeMode: Flow<ShadeMode>,
+): Flow<FooterActionsButtonViewModel?> {
+ return shadeMode.map { mode ->
+ val isDualShade = mode is ShadeMode.Dual
+ FooterActionsButtonViewModel(
+ id = R.id.pm_lite,
+ Icon.Resource(
+ android.R.drawable.ic_lock_power_off,
+ ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
),
- backgroundColor = if (DualShade.isEnabled) R.attr.shadeInactive else R.attr.shadeActive,
- onPowerButtonClicked,
- )
+ iconTint =
+ Utils.getColorAttrDefaultColor(
+ qsThemedContext,
+ if (isDualShade) R.attr.onShadeInactiveVariant else R.attr.onShadeActive,
+ ),
+ backgroundColor = if (isDualShade) R.attr.shadeInactive else R.attr.shadeActive,
+ onPowerButtonClicked,
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt
index eeec9b3ef5e6..f83c2fcc12e4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/LargeTileSpanRepository.kt
@@ -25,14 +25,12 @@ import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class LargeTileSpanRepository
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
index 693681d090d8..b45d3629fec7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSColumnsRepository.kt
@@ -23,12 +23,10 @@ import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapLatest
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class QSColumnsRepository
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt
index b0c607303297..19e4fd5b21b0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt
@@ -34,7 +34,6 @@ import com.android.systemui.util.kotlin.SharedPreferencesExt.observe
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
@@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
/** Repository for QS user preferences. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class QSPreferencesRepository
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt
index e493cbeebae8..b94975425803 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractor.kt
@@ -22,12 +22,10 @@ import com.android.systemui.qs.panels.shared.model.GridLayoutType
import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
class GridLayoutTypeInteractor
@Inject
constructor(private val repo: GridLayoutTypeRepository, shadeModeInteractor: ShadeModeInteractor) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt
index 11ea60e874b3..2b2a63b1fded 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSColumnsInteractor.kt
@@ -23,7 +23,6 @@ import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
@@ -37,7 +36,6 @@ constructor(
repo: QSColumnsRepository,
shadeInteractor: ShadeInteractor,
) {
- @OptIn(ExperimentalCoroutinesApi::class)
val columns: StateFlow<Int> =
shadeInteractor.shadeMode
.flatMapLatest {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
index 2cccaddc02a8..1f4f9f98c5b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
@@ -153,7 +153,6 @@ import com.android.systemui.res.R
import kotlin.math.abs
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
object TileType
@@ -293,7 +292,6 @@ fun DefaultEditTileGrid(
}
}
-@OptIn(ExperimentalCoroutinesApi::class)
@Composable
private fun AutoScrollGrid(
listState: EditTileListState,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
index 37b1642be57b..59c554c28df6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
@@ -43,6 +43,7 @@ fun Toolbar(toolbarViewModelFactory: ToolbarViewModel.Factory, modifier: Modifie
)
Spacer(modifier = Modifier.weight(1f))
- IconButton(viewModel.powerButtonViewModel, Modifier.sysuiResTag("pm_lite"))
+
+ viewModel.powerButtonViewModel?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt
index f7ed1adecb34..2082423f1fd3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt
@@ -42,7 +42,6 @@ import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -55,7 +54,6 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
class EditModeViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
index 127ecb2f3eba..29832b9c272c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileGridViewModel.kt
@@ -25,7 +25,6 @@ import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -33,7 +32,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class TileGridViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt
index 0fde855f576f..1a6653c38f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt
@@ -34,6 +34,7 @@ import com.android.systemui.qs.footer.ui.viewmodel.settingsButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.userSwitcherViewModel
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
+import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Provider
@@ -48,13 +49,24 @@ constructor(
private val footerActionsInteractor: FooterActionsInteractor,
private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>,
private val falsingInteractor: FalsingInteractor,
+ shadeModeInteractor: ShadeModeInteractor,
@ShadeDisplayAware appContext: Context,
) : ExclusiveActivatable() {
private val qsThemedContext =
ContextThemeWrapper(appContext, R.style.Theme_SystemUI_QuickSettings)
private val hydrator = Hydrator("ToolbarViewModel.hydrator")
- val powerButtonViewModel = powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked)
+ val powerButtonViewModel: FooterActionsButtonViewModel? by
+ hydrator.hydratedStateOf(
+ traceName = "powerButtonViewModel",
+ initialValue = null,
+ source =
+ powerButtonViewModel(
+ qsThemedContext,
+ ::onPowerButtonClicked,
+ shadeModeInteractor.shadeMode,
+ ),
+ )
val settingsButtonViewModel =
settingsButtonViewModel(qsThemedContext, ::onSettingsButtonClicked)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt
index a2bb9e9a2f63..1cd5d100ec00 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt
@@ -20,7 +20,6 @@ import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -75,7 +74,6 @@ constructor(
}
.emitOnStart()
- @OptIn(ExperimentalCoroutinesApi::class)
override val restoreData =
run {
val mutex = Mutex()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
index c6751b7717e2..4e993786e343 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
@@ -27,7 +27,6 @@ import com.android.systemui.res.R
import com.android.systemui.retail.data.repository.RetailModeRepository
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -87,7 +86,6 @@ interface TileSpecRepository {
* If the device is in retail mode, the tiles are fixed to the value of
* [R.string.quick_settings_tiles_retail_mode].
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class TileSpecSettingsRepository
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
index 2bb6bba51dbd..609541ba1ab6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
@@ -52,7 +52,6 @@ import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -133,7 +132,6 @@ interface CurrentTilesInteractor : ProtoDumpable {
* * Platform tiles will be kept between users, with a call to [QSTile.userSwitch]
* * [CustomTile]s will only be destroyed if the user changes.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CurrentTilesInteractorImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt
index 180e0feea2ab..1a2847818edf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt
@@ -11,7 +11,6 @@ import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.take
@@ -40,7 +39,6 @@ constructor(
@Background private val backgroundDispatcher: CoroutineDispatcher,
) {
- @OptIn(ExperimentalCoroutinesApi::class)
fun start() {
applicationScope.launch(context = backgroundDispatcher) {
qsSettingsRestoredRepository.restoreData
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
index 6d3e5d07c251..b1f99cccff70 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTileNewImpl.kt
@@ -61,6 +61,7 @@ constructor(
private val internetDialogManager: InternetDialogManager,
private val wifiStateWorker: WifiStateWorker,
private val accessPointController: AccessPointController,
+ private val internetDetailsViewModelFactory: InternetDetailsViewModel.Factory,
) :
QSTileImpl<QSTile.BooleanState>(
host,
@@ -107,7 +108,7 @@ constructor(
}
override fun getDetailsViewModel(): TileDetailsViewModel {
- return InternetDetailsViewModel { longClick(null) }
+ return internetDetailsViewModelFactory.create { longClick(null) }
}
override fun handleSecondaryClick(expandable: Expandable?) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
index 224fa104168d..30bf5b309a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
@@ -40,7 +40,6 @@ import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
@@ -70,7 +69,6 @@ import kotlinx.coroutines.flow.transformLatest
* Don't use this constructor directly. Instead, inject [QSTileViewModelFactory] to create a new
* instance of this class.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
class QSTileViewModelImpl<DATA_TYPE>(
override val config: QSTileConfig,
private val userActionInteractor: () -> QSTileUserActionInteractor<DATA_TYPE>,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManager.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManager.kt
index c64532a2c4ba..733159e285e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManager.kt
@@ -57,10 +57,8 @@ import com.android.settingslib.satellite.SatelliteDialogUtils.mayStartSatelliteW
import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils
import com.android.systemui.Prefs
import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan
-import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.qs.flags.QsDetailedView
import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -75,11 +73,7 @@ import kotlinx.coroutines.Job
/**
* View content for the Internet tile details that handles all UI interactions and state management.
- *
- * @param internetDialog non-null if the details should be shown as part of a dialog and null
- * otherwise.
*/
-// TODO: b/377388104 Make this content for details view only.
class InternetDetailsContentManager
@AssistedInject
constructor(
@@ -88,9 +82,7 @@ constructor(
@Assisted(CAN_CONFIG_WIFI) private val canConfigWifi: Boolean,
@Assisted private val coroutineScope: CoroutineScope,
@Assisted private var context: Context,
- @Assisted private var internetDialog: SystemUIDialog?,
private val uiEventLogger: UiEventLogger,
- private val dialogTransitionAnimator: DialogTransitionAnimator,
@Main private val handler: Handler,
@Background private val backgroundExecutor: Executor,
private val keyguard: KeyguardStateController,
@@ -104,8 +96,6 @@ constructor(
// UI Components
private lateinit var contentView: View
- private lateinit var internetDialogTitleView: TextView
- private lateinit var internetDialogSubTitleView: TextView
private lateinit var divider: View
private lateinit var progressBar: ProgressBar
private lateinit var ethernetLayout: LinearLayout
@@ -132,7 +122,6 @@ constructor(
private lateinit var shareWifiButton: Button
private lateinit var airplaneModeButton: Button
private var alertDialog: AlertDialog? = null
- private lateinit var doneButton: Button
private val canChangeWifiState =
WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context)
@@ -153,7 +142,6 @@ constructor(
@Assisted(CAN_CONFIG_WIFI) canConfigWifi: Boolean,
coroutineScope: CoroutineScope,
context: Context,
- internetDialog: SystemUIDialog?,
): InternetDetailsContentManager
}
@@ -209,8 +197,6 @@ constructor(
}
// Network layouts
- internetDialogTitleView = contentView.requireViewById(R.id.internet_dialog_title)
- internetDialogSubTitleView = contentView.requireViewById(R.id.internet_dialog_subtitle)
divider = contentView.requireViewById(R.id.divider)
progressBar = contentView.requireViewById(R.id.wifi_searching_progress)
@@ -219,15 +205,6 @@ constructor(
setMobileLayout()
ethernetLayout = contentView.requireViewById(R.id.ethernet_layout)
- // Done button is only visible for the dialog view
- doneButton = contentView.requireViewById(R.id.done_button)
- if (internetDialog == null) {
- doneButton.visibility = View.GONE
- } else {
- // Set done button if qs details view is not enabled.
- doneButton.setOnClickListener { internetDialog!!.dismiss() }
- }
-
// Share WiFi
shareWifiButton = contentView.requireViewById(R.id.share_wifi_button)
shareWifiButton.setOnClickListener { view ->
@@ -251,6 +228,17 @@ constructor(
// Background drawables
backgroundOn = context.getDrawable(R.drawable.settingslib_switch_bar_bg_on)
backgroundOff = context.getDrawable(R.drawable.internet_dialog_selected_effect)
+
+ // Done button is only visible for the dialog view
+ contentView.findViewById<Button>(R.id.done_button).apply { visibility = View.GONE }
+
+ // Title and subtitle will be added in the `TileDetails`
+ contentView.findViewById<TextView>(R.id.internet_dialog_title).apply {
+ visibility = View.GONE
+ }
+ contentView.findViewById<TextView>(R.id.internet_dialog_subtitle).apply {
+ visibility = View.GONE
+ }
}
private fun setWifiLayout() {
@@ -336,21 +324,19 @@ constructor(
}
}
- private fun getDialogTitleText(): CharSequence {
- return internetDetailsContentController.getDialogTitleText()
+ fun getTitleText(): String {
+ return internetDetailsContentController.getDialogTitleText().toString()
+ }
+
+ fun getSubtitleText(): String {
+ return internetDetailsContentController.getSubtitleText(isProgressBarVisible).toString()
}
private fun updateDetailsUI(internetContent: InternetContent) {
if (DEBUG) {
Log.d(TAG, "updateDetailsUI ")
}
- if (QsDetailedView.isEnabled) {
- internetDialogTitleView.visibility = View.GONE
- internetDialogSubTitleView.visibility = View.GONE
- } else {
- internetDialogTitleView.text = internetContent.internetDialogTitleString
- internetDialogSubTitleView.text = internetContent.internetDialogSubTitle
- }
+
airplaneModeButton.visibility =
if (internetContent.isAirplaneModeEnabled) View.VISIBLE else View.GONE
@@ -361,17 +347,11 @@ constructor(
private fun getStartingInternetContent(): InternetContent {
return InternetContent(
- internetDialogTitleString = getDialogTitleText(),
- internetDialogSubTitle = getSubtitleText(),
isWifiEnabled = internetDetailsContentController.isWifiEnabled,
isDeviceLocked = internetDetailsContentController.isDeviceLocked,
)
}
- private fun getSubtitleText(): String {
- return internetDetailsContentController.getSubtitleText(isProgressBarVisible).toString()
- }
-
@VisibleForTesting
internal fun hideWifiViews() {
setProgressBarVisible(false)
@@ -393,7 +373,6 @@ constructor(
progressBar.visibility = if (visible) View.VISIBLE else View.GONE
progressBar.isIndeterminate = visible
divider.visibility = if (visible) View.GONE else View.VISIBLE
- internetDialogSubTitleView.text = getSubtitleText()
}
private fun showTurnOffAutoDataSwitchDialog(subId: Int) {
@@ -418,12 +397,7 @@ constructor(
SystemUIDialog.setShowForAllUsers(alertDialog, true)
SystemUIDialog.registerDismissListener(alertDialog)
SystemUIDialog.setWindowOnTop(alertDialog, keyguard.isShowing())
- if (QsDetailedView.isEnabled) {
- alertDialog!!.show()
- } else {
- dialogTransitionAnimator.showFromDialog(alertDialog!!, internetDialog!!, null, false)
- Log.e(TAG, "Internet dialog is shown with the refactor code")
- }
+ alertDialog!!.show()
}
private fun shouldShowMobileDialog(): Boolean {
@@ -466,11 +440,8 @@ constructor(
SystemUIDialog.setShowForAllUsers(alertDialog, true)
SystemUIDialog.registerDismissListener(alertDialog)
SystemUIDialog.setWindowOnTop(alertDialog, keyguard.isShowing())
- if (QsDetailedView.isEnabled) {
- alertDialog!!.show()
- } else {
- dialogTransitionAnimator.showFromDialog(alertDialog!!, internetDialog!!, null, false)
- }
+
+ alertDialog!!.show()
}
private fun onClickConnectedWifi(view: View?) {
@@ -803,7 +774,6 @@ constructor(
secondaryMobileNetworkLayout?.setOnClickListener(null)
seeAllLayout.setOnClickListener(null)
wifiToggle.setOnCheckedChangeListener(null)
- doneButton.setOnClickListener(null)
shareWifiButton.setOnClickListener(null)
airplaneModeButton.setOnClickListener(null)
internetDetailsContentController.onStop()
@@ -825,8 +795,6 @@ constructor(
private fun getInternetContent(shouldUpdateMobileNetwork: Boolean): InternetContent {
return InternetContent(
shouldUpdateMobileNetwork = shouldUpdateMobileNetwork,
- internetDialogTitleString = getDialogTitleText(),
- internetDialogSubTitle = getSubtitleText(),
activeNetworkIsCellular =
if (shouldUpdateMobileNetwork)
internetDetailsContentController.activeNetworkIsCellular()
@@ -924,10 +892,7 @@ constructor(
if (DEBUG) {
Log.d(TAG, "dismissDialog")
}
- if (internetDialog != null) {
- internetDialog!!.dismiss()
- internetDialog = null
- }
+ // TODO: b/377388104 Close details view
}
override fun onAccessPointsChanged(
@@ -967,8 +932,6 @@ constructor(
@VisibleForTesting
data class InternetContent(
- val internetDialogTitleString: CharSequence,
- val internetDialogSubTitle: CharSequence,
val isAirplaneModeEnabled: Boolean = false,
val hasEthernet: Boolean = false,
val shouldUpdateMobileNetwork: Boolean = false,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
index f239a179d79a..df4dddbca9e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDetailsViewModel.kt
@@ -16,44 +16,93 @@
package com.android.systemui.qs.tiles.dialog
+import android.util.Log
import android.view.LayoutInflater
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.android.systemui.plugins.qs.TileDetailsViewModel
import com.android.systemui.res.R
+import com.android.systemui.statusbar.connectivity.AccessPointController
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
-class InternetDetailsViewModel(
- onLongClick: () -> Unit,
+class InternetDetailsViewModel
+@AssistedInject
+constructor(
+ private val accessPointController: AccessPointController,
+ private val contentManagerFactory: InternetDetailsContentManager.Factory,
+ @Assisted private val onLongClick: () -> Unit,
) : TileDetailsViewModel() {
- private val _onLongClick = onLongClick
+ private lateinit var internetDetailsContentManager: InternetDetailsContentManager
@Composable
override fun GetContentView() {
+ val coroutineScope = rememberCoroutineScope()
+ val context = LocalContext.current
+
+ internetDetailsContentManager = remember {
+ contentManagerFactory.create(
+ canConfigMobileData = accessPointController.canConfigMobileData(),
+ canConfigWifi = accessPointController.canConfigWifi(),
+ coroutineScope = coroutineScope,
+ context = context,
+ )
+ }
AndroidView(
modifier = Modifier.fillMaxWidth().fillMaxHeight(),
factory = { context ->
- // Inflate with the existing dialog xml layout
- LayoutInflater.from(context)
- .inflate(R.layout.internet_connectivity_dialog, null)
- // TODO: b/377388104 - Implement the internet details view
+ // Inflate with the existing dialog xml layout and bind it with the manager
+ val view =
+ LayoutInflater.from(context)
+ .inflate(R.layout.internet_connectivity_dialog, null)
+ internetDetailsContentManager.bind(view)
+
+ view
+ // TODO: b/377388104 - Polish the internet details view UI
+ },
+ onRelease = {
+ internetDetailsContentManager.unBind()
+ if (DEBUG) {
+ Log.d(TAG, "onRelease")
+ }
},
)
}
override fun clickOnSettingsButton() {
- _onLongClick()
+ onLongClick()
}
override fun getTitle(): String {
+ // TODO: b/377388104 make title and sub title mutable states of string
+ // by internetDetailsContentManager.getTitleText()
+ // TODO: test title change between airplane mode and not airplane mode
// TODO: b/377388104 Update the placeholder text
return "Internet"
}
override fun getSubTitle(): String {
+ // TODO: b/377388104 make title and sub title mutable states of string
+ // by internetDetailsContentManager.getSubtitleText()
+ // TODO: test subtitle change between airplane mode and not airplane mode
// TODO: b/377388104 Update the placeholder text
return "Tab a network to connect"
}
+
+ @AssistedFactory
+ interface Factory {
+ fun create(onLongClick: () -> Unit): InternetDetailsViewModel
+ }
+
+ companion object {
+ private const val TAG = "InternetDetailsVModel"
+ private val DEBUG: Boolean = Log.isLoggable(TAG, Log.DEBUG)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt
index 4806c3f83224..0b0f2feaa909 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt
@@ -22,6 +22,7 @@ import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
+import com.android.systemui.qs.tiles.base.logging.QSTileLogger
import com.android.systemui.qs.tiles.impl.custom.data.entity.CustomTileDefaults
import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileDefaultsRepository
import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTilePackageUpdatesRepository
@@ -31,7 +32,6 @@ import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -47,7 +47,6 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
@QSTileScope
-@OptIn(ExperimentalCoroutinesApi::class)
class CustomTileDataInteractor
@Inject
constructor(
@@ -58,6 +57,7 @@ constructor(
private val packageUpdatesRepository: CustomTilePackageUpdatesRepository,
userRepository: UserRepository,
@QSTileScope private val tileScope: CoroutineScope,
+ qsTileLogger: QSTileLogger,
) : QSTileDataInteractor<CustomTileDataModel> {
private val mutableUserFlow = MutableStateFlow(userRepository.getSelectedUserInfo().userHandle)
@@ -71,6 +71,7 @@ constructor(
// binding the service might access it
customTileInteractor.initForUser(user)
// Bind the TileService for not active tile
+ qsTileLogger.logInfo(tileSpec, "onBindingFlow for user:$user")
serviceInteractor.bindOnStart()
packageUpdatesRepository
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileServiceInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileServiceInteractor.kt
index ccc84c091b1b..c0fc93fc914b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileServiceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileServiceInteractor.kt
@@ -25,6 +25,7 @@ import android.os.UserHandle
import android.service.quicksettings.IQSTileService
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.qs.external.CustomTileInterface
import com.android.systemui.qs.external.TileServiceManager
@@ -36,20 +37,17 @@ import com.android.systemui.user.data.repository.UserRepository
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.produce
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
-import com.android.app.tracing.coroutines.launchTraced as launch
/**
* Communicates with [TileService] via [TileServiceManager] and [IQSTileService]. This interactor is
* also responsible for the binding to the [TileService].
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@QSTileScope
class CustomTileServiceInteractor
@Inject
@@ -74,6 +72,7 @@ constructor(
val callingAppIds: Flow<Int>
get() = tileReceivingInterface.mutableCallingAppIds
+
val refreshEvents: Flow<Unit>
get() = tileReceivingInterface.mutableRefreshEvents
@@ -146,6 +145,7 @@ constructor(
private fun getTileServiceManager(): TileServiceManager =
synchronized(tileServices) {
+ qsTileLogger.logInfo(tileSpec, "getTileServiceManager called")
if (tileServiceManager == null) {
tileServices
.getTileWrapper(tileReceivingInterface)
@@ -175,8 +175,10 @@ constructor(
override val user: Int
get() = currentUser.identifier
+
override val qsTile: Tile
get() = customTileInteractor.getTile(currentUser)
+
override val component: ComponentName = tileSpec.componentName
val mutableCallingAppIds = MutableStateFlow(Process.INVALID_UID)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt
index 6d10843decc0..871c051722c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt
@@ -41,7 +41,6 @@ import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -50,7 +49,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
/** Observes internet state changes providing the [InternetTileModel]. */
class InternetTileDataInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
index c4f9515b819f..6e2c437b9c16 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileUserActionInteractor.kt
@@ -43,6 +43,7 @@ constructor(
private val wifiStateWorker: WifiStateWorker,
private val accessPointController: AccessPointController,
private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
+ private val internetDetailsViewModelFactory: InternetDetailsViewModel.Factory,
) : QSTileUserActionInteractor<InternetTileModel> {
override suspend fun handleInput(input: QSTileInput<InternetTileModel>): Unit =
@@ -70,7 +71,7 @@ constructor(
}
override val detailsViewModel: TileDetailsViewModel =
- InternetDetailsViewModel { handleLongClick(null) }
+ internetDetailsViewModelFactory.create { handleLongClick(null) }
private fun handleLongClick(expandable:Expandable?){
qsTileIntentUserActionHandler.handle(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
index 000f7f8a7d31..5bc26f50f70f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
@@ -21,7 +21,8 @@ import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.UserActionResult.HideOverlay
-import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay
+import com.android.compose.animation.scene.UserActionResult.ShowOverlay.HideCurrentOverlays
import com.android.systemui.qs.panels.ui.viewmodel.EditModeViewModel
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
@@ -47,7 +48,11 @@ constructor(private val editModeViewModel: EditModeViewModel) : UserActionsViewM
}
put(
Swipe.Down(fromSource = SceneContainerEdge.TopLeft),
- ReplaceByOverlay(Overlays.NotificationsShade),
+ ShowOverlay(
+ Overlays.NotificationsShade,
+ hideCurrentOverlays =
+ HideCurrentOverlays.Some(Overlays.QuickSettingsShade),
+ ),
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java
index 60c2cca1ae8b..9af4630bf492 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/LauncherProxyService.java
@@ -100,14 +100,14 @@ import com.android.systemui.navigationbar.views.NavigationBar;
import com.android.systemui.navigationbar.views.NavigationBarView;
import com.android.systemui.navigationbar.views.buttons.KeyButtonView;
import com.android.systemui.process.ProcessWrapper;
-import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
+import com.android.systemui.recents.LauncherProxyService.LauncherProxyListener;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
-import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.recents.ILauncherProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
@@ -135,16 +135,16 @@ import javax.inject.Inject;
import javax.inject.Provider;
/**
- * Class to send information from overview to launcher with a binder.
+ * Class to send information from SysUI to Launcher with a binder.
*/
@SysUISingleton
-public class OverviewProxyService implements CallbackController<OverviewProxyListener>,
+public class LauncherProxyService implements CallbackController<LauncherProxyListener>,
NavigationModeController.ModeChangedListener, Dumpable {
@VisibleForTesting
static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
- public static final String TAG_OPS = "OverviewProxyService";
+ public static final String TAG_OPS = "LauncherProxyService";
private static final long BACKOFF_MILLIS = 1000;
private static final long DEFERRED_CALLBACK_MILLIS = 5000;
// Max backoff caps at 5 mins
@@ -165,7 +165,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final Runnable mConnectionRunnable = () ->
internalConnectToCurrentUser("runnable: startConnectionToCurrentUser");
private final ComponentName mRecentsComponentName;
- private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>();
+ private final List<LauncherProxyListener> mConnectionCallbacks = new ArrayList<>();
private final Intent mQuickStepIntent;
private final ScreenshotHelper mScreenshotHelper;
private final CommandQueue mCommandQueue;
@@ -179,12 +179,12 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final BroadcastDispatcher mBroadcastDispatcher;
private final BackAnimation mBackAnimation;
- private IOverviewProxy mOverviewProxy;
+ private ILauncherProxy mLauncherProxy;
private int mConnectionBackoffAttempts;
private boolean mBound;
private boolean mIsEnabled;
- // This is set to false when the overview service is requested to be bound until it is notified
- // that the previous service has been cleaned up in IOverviewProxy#onUnbind(). It is also set to
+ // This is set to false when the launcher service is requested to be bound until it is notified
+ // that the previous service has been cleaned up in ILauncherProxy#onUnbind(). It is also set to
// true after a 1000ms timeout by mDeferredBindAfterTimedOutCleanup.
private boolean mIsPrevServiceCleanedUp = true;
@@ -341,7 +341,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
@Override
public void updateContextualEduStats(boolean isTrackpadGesture, String gestureType) {
verifyCallerAndClearCallingIdentityPostMain("updateContextualEduStats",
- () -> mHandler.post(() -> OverviewProxyService.this.updateContextualEduStats(
+ () -> mHandler.post(() -> LauncherProxyService.this.updateContextualEduStats(
isTrackpadGesture, GestureType.valueOf(gestureType))));
}
@@ -504,7 +504,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public void onReceive(Context context, Intent intent) {
if (Objects.equals(intent.getAction(), Intent.ACTION_USER_UNLOCKED)) {
if (keyguardPrivateNotifications()) {
- // Start the overview connection to the launcher service
+ // Start the launcher connection to the launcher service
// Connect if user hasn't connected yet
if (getProxy() == null) {
startConnectionToCurrentUser();
@@ -546,14 +546,14 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
};
- private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {
+ private final ServiceConnection mLauncherServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- Log.d(TAG_OPS, "Overview proxy service connected");
+ Log.d(TAG_OPS, "Launcher proxy service connected");
mConnectionBackoffAttempts = 0;
mHandler.removeCallbacks(mDeferredConnectionCallback);
try {
- service.linkToDeath(mOverviewServiceDeathRcpt, 0);
+ service.linkToDeath(mLauncherServiceDeathRcpt, 0);
} catch (RemoteException e) {
// Failed to link to death (process may have died between binding and connecting),
// just unbind the service for now and retry again
@@ -564,7 +564,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
mCurrentBoundedUserId = mUserTracker.getUserId();
- mOverviewProxy = IOverviewProxy.Stub.asInterface(service);
+ mLauncherProxy = ILauncherProxy.Stub.asInterface(service);
Bundle params = new Bundle();
addInterface(mSysUiProxy, params);
@@ -574,8 +574,8 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mShellInterface.createExternalInterfaces(params);
try {
- Log.d(TAG_OPS, "OverviewProxyService connected, initializing overview proxy");
- mOverviewProxy.onInitialize(params);
+ Log.d(TAG_OPS, "LauncherProxyService connected, initializing launcher proxy");
+ mLauncherProxy.onInitialize(params);
} catch (RemoteException e) {
mCurrentBoundedUserId = -1;
Log.e(TAG_OPS, "Failed to call onInitialize()", e);
@@ -614,7 +614,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final StatusBarWindowCallback mStatusBarWindowCallback = this::onStatusBarStateChanged;
// This is the death handler for the binder from the launcher service
- private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
+ private final IBinder.DeathRecipient mLauncherServiceDeathRcpt
= this::cleanupAfterDeath;
private final IVoiceInteractionSessionListener mVoiceInteractionSessionListener =
@@ -632,7 +632,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
@Override
public void onVoiceSessionWindowVisibilityChanged(boolean visible) {
mContext.getMainExecutor().execute(() ->
- OverviewProxyService.this.onVoiceSessionWindowVisibilityChanged(visible));
+ LauncherProxyService.this.onVoiceSessionWindowVisibilityChanged(visible));
}
@Override
@@ -652,7 +652,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
- public OverviewProxyService(Context context,
+ public LauncherProxyService(Context context,
@Main Executor mainExecutor,
CommandQueue commandQueue,
ShellInterface shellInterface,
@@ -755,14 +755,14 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
@Override
public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
- if (mOverviewProxy != null) {
+ if (mLauncherProxy != null) {
try {
if (DesktopModeStatus.canEnterDesktopMode(mContext)
&& (sysUiState.getFlags()
& SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0) {
return;
}
- mOverviewProxy.enterStageSplitFromRunningApp(leftOrTop);
+ mLauncherProxy.enterStageSplitFromRunningApp(leftOrTop);
} catch (RemoteException e) {
Log.w(TAG_OPS, "Unable to enter stage split from the current running app");
}
@@ -817,12 +817,12 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private void notifySystemUiStateFlags(@SystemUiStateFlags long flags) {
if (SysUiState.DEBUG) {
- Log.d(TAG_OPS, "Notifying sysui state change to overview service: proxy="
- + mOverviewProxy + " flags=" + flags);
+ Log.d(TAG_OPS, "Notifying sysui state change to launcher service: proxy="
+ + mLauncherProxy + " flags=" + flags);
}
try {
- if (mOverviewProxy != null) {
- mOverviewProxy.onSystemUiStateChanged(flags);
+ if (mLauncherProxy != null) {
+ mLauncherProxy.onSystemUiStateChanged(flags);
}
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to notify sysui state change", e);
@@ -854,9 +854,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
private void dispatchNavButtonBounds() {
- if (mOverviewProxy != null && mActiveNavBarRegion != null) {
+ if (mLauncherProxy != null && mActiveNavBarRegion != null) {
try {
- mOverviewProxy.onActiveNavBarRegionChanges(mActiveNavBarRegion);
+ mLauncherProxy.onActiveNavBarRegionChanges(mActiveNavBarRegion);
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call onActiveNavBarRegionChanges()", e);
}
@@ -888,7 +888,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
// This should not happen, but if any per-user SysUI component has a dependency on OPS,
// then this could get triggered
Log.w(TAG_OPS,
- "Skipping connection to overview service due to non-system foreground user "
+ "Skipping connection to launcher service due to non-system foreground user "
+ "caller");
return;
}
@@ -925,7 +925,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
try {
mBound = mContext.bindServiceAsUser(mQuickStepIntent,
- mOverviewServiceConnection,
+ mLauncherServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
currentUser);
} catch (SecurityException e) {
@@ -954,15 +954,15 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
@Override
- public void addCallback(@NonNull OverviewProxyListener listener) {
+ public void addCallback(@NonNull LauncherProxyListener listener) {
if (!mConnectionCallbacks.contains(listener)) {
mConnectionCallbacks.add(listener);
}
- listener.onConnectionChanged(mOverviewProxy != null);
+ listener.onConnectionChanged(mLauncherProxy != null);
}
@Override
- public void removeCallback(@NonNull OverviewProxyListener listener) {
+ public void removeCallback(@NonNull LauncherProxyListener listener) {
mConnectionCallbacks.remove(listener);
}
@@ -974,21 +974,21 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
return mIsEnabled;
}
- public IOverviewProxy getProxy() {
- return mOverviewProxy;
+ public ILauncherProxy getProxy() {
+ return mLauncherProxy;
}
private void disconnectFromLauncherService(String disconnectReason) {
Log.d(TAG_OPS, "disconnectFromLauncherService bound?: " + mBound +
- " currentProxy: " + mOverviewProxy + " disconnectReason: " + disconnectReason,
+ " currentProxy: " + mLauncherProxy + " disconnectReason: " + disconnectReason,
new Throwable());
if (mBound) {
// Always unbind the service (ie. if called through onNullBinding or onBindingDied)
- mContext.unbindService(mOverviewServiceConnection);
+ mContext.unbindService(mLauncherServiceConnection);
mBound = false;
- if (mOverviewProxy != null) {
+ if (mLauncherProxy != null) {
try {
- mOverviewProxy.onUnbind(new IRemoteCallback.Stub() {
+ mLauncherProxy.onUnbind(new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle data) throws RemoteException {
// Received Launcher reply, try to bind anew.
@@ -1006,9 +1006,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
}
- if (mOverviewProxy != null) {
- mOverviewProxy.asBinder().unlinkToDeath(mOverviewServiceDeathRcpt, 0);
- mOverviewProxy = null;
+ if (mLauncherProxy != null) {
+ mLauncherProxy.asBinder().unlinkToDeath(mLauncherServiceDeathRcpt, 0);
+ mLauncherProxy = null;
notifyConnectionChanged();
}
}
@@ -1044,7 +1044,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private void notifyConnectionChanged() {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
- mConnectionCallbacks.get(i).onConnectionChanged(mOverviewProxy != null);
+ mConnectionCallbacks.get(i).onConnectionChanged(mLauncherProxy != null);
}
}
@@ -1095,10 +1095,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public void notifyAssistantVisibilityChanged(float visibility) {
try {
- if (mOverviewProxy != null) {
- mOverviewProxy.onAssistantVisibilityChanged(visibility);
+ if (mLauncherProxy != null) {
+ mLauncherProxy.onAssistantVisibilityChanged(visibility);
} else {
- Log.e(TAG_OPS, "Failed to get overview proxy for assistant visibility.");
+ Log.e(TAG_OPS, "Failed to get launcher proxy for assistant visibility.");
}
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call notifyAssistantVisibilityChanged()", e);
@@ -1148,10 +1148,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public void disable(int displayId, int state1, int state2, boolean animate) {
try {
- if (mOverviewProxy != null) {
- mOverviewProxy.disable(displayId, state1, state2, animate);
+ if (mLauncherProxy != null) {
+ mLauncherProxy.disable(displayId, state1, state2, animate);
} else {
- Log.e(TAG_OPS, "Failed to get overview proxy for disable flags.");
+ Log.e(TAG_OPS, "Failed to get launcher proxy for disable flags.");
}
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call disable()", e);
@@ -1160,10 +1160,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public void onRotationProposal(int rotation, boolean isValid) {
try {
- if (mOverviewProxy != null) {
- mOverviewProxy.onRotationProposal(rotation, isValid);
+ if (mLauncherProxy != null) {
+ mLauncherProxy.onRotationProposal(rotation, isValid);
} else {
- Log.e(TAG_OPS, "Failed to get overview proxy for proposing rotation.");
+ Log.e(TAG_OPS, "Failed to get launcher proxy for proposing rotation.");
}
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call onRotationProposal()", e);
@@ -1172,10 +1172,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public void onSystemBarAttributesChanged(int displayId, int behavior) {
try {
- if (mOverviewProxy != null) {
- mOverviewProxy.onSystemBarAttributesChanged(displayId, behavior);
+ if (mLauncherProxy != null) {
+ mLauncherProxy.onSystemBarAttributesChanged(displayId, behavior);
} else {
- Log.e(TAG_OPS, "Failed to get overview proxy for system bar attr change.");
+ Log.e(TAG_OPS, "Failed to get launcher proxy for system bar attr change.");
}
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call onSystemBarAttributesChanged()", e);
@@ -1184,10 +1184,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
try {
- if (mOverviewProxy != null) {
- mOverviewProxy.onNavButtonsDarkIntensityChanged(darkIntensity);
+ if (mLauncherProxy != null) {
+ mLauncherProxy.onNavButtonsDarkIntensityChanged(darkIntensity);
} else {
- Log.e(TAG_OPS, "Failed to get overview proxy to update nav buttons dark intensity");
+ Log.e(TAG_OPS, "Failed to get launcher proxy to update nav buttons dark intensity");
}
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call onNavButtonsDarkIntensityChanged()", e);
@@ -1196,10 +1196,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
public void onNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {
try {
- if (mOverviewProxy != null) {
- mOverviewProxy.onNavigationBarLumaSamplingEnabled(displayId, enable);
+ if (mLauncherProxy != null) {
+ mLauncherProxy.onNavigationBarLumaSamplingEnabled(displayId, enable);
} else {
- Log.e(TAG_OPS, "Failed to get overview proxy to enable/disable nav bar luma"
+ Log.e(TAG_OPS, "Failed to get launcher proxy to enable/disable nav bar luma"
+ "sampling");
}
} catch (RemoteException e) {
@@ -1221,7 +1221,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
@Override
public void dump(PrintWriter pw, String[] args) {
pw.println(TAG_OPS + " state:");
- pw.print(" isConnected="); pw.println(mOverviewProxy != null);
+ pw.print(" isConnected="); pw.println(mLauncherProxy != null);
pw.print(" mIsEnabled="); pw.println(isEnabled());
pw.print(" mRecentsComponentName="); pw.println(mRecentsComponentName);
pw.print(" mQuickStepIntent="); pw.println(mQuickStepIntent);
@@ -1237,7 +1237,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mSysUiState.dump(pw, args);
}
- public interface OverviewProxyListener {
+ public interface LauncherProxyListener {
default void onConnectionChanged(boolean isConnected) {}
default void onPrioritizedRotation(@Surface.Rotation int rotation) {}
default void onOverviewShown(boolean fromHome) {}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 21c5ae8aec40..e51b73dd96c6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -23,30 +23,30 @@ import android.util.Log;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.recents.ILauncherProxy;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import javax.inject.Inject;
/**
- * An implementation of the Recents interface which proxies to the OverviewProxyService.
+ * An implementation of the Recents interface which proxies to the LauncherProxyService.
*/
@SysUISingleton
public class OverviewProxyRecentsImpl implements RecentsImplementation {
private final static String TAG = "OverviewProxyRecentsImpl";
private Handler mHandler;
- private final OverviewProxyService mOverviewProxyService;
+ private final LauncherProxyService mLauncherProxyService;
private final ActivityStarter mActivityStarter;
private final KeyguardStateController mKeyguardStateController;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
public OverviewProxyRecentsImpl(
- OverviewProxyService overviewProxyService,
+ LauncherProxyService launcherProxyService,
ActivityStarter activityStarter,
KeyguardStateController keyguardStateController) {
- mOverviewProxyService = overviewProxyService;
+ mLauncherProxyService = launcherProxyService;
mActivityStarter = activityStarter;
mKeyguardStateController = keyguardStateController;
}
@@ -58,10 +58,10 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
@Override
public void showRecentApps(boolean triggeredFromAltTab) {
- IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null) {
+ ILauncherProxy launcherProxy = mLauncherProxyService.getProxy();
+ if (launcherProxy != null) {
try {
- overviewProxy.onOverviewShown(triggeredFromAltTab);
+ launcherProxy.onOverviewShown(triggeredFromAltTab);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send overview show event to launcher.", e);
}
@@ -70,10 +70,10 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
@Override
public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null) {
+ ILauncherProxy launcherProxy = mLauncherProxyService.getProxy();
+ if (launcherProxy != null) {
try {
- overviewProxy.onOverviewHidden(triggeredFromAltTab, triggeredFromHomeKey);
+ launcherProxy.onOverviewHidden(triggeredFromAltTab, triggeredFromHomeKey);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send overview hide event to launcher.", e);
}
@@ -83,13 +83,13 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
@Override
public void toggleRecentApps() {
// If connected to launcher service, let it handle the toggle logic
- IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null) {
+ ILauncherProxy launcherProxy = mLauncherProxyService.getProxy();
+ if (launcherProxy != null) {
final Runnable toggleRecents = () -> {
try {
- if (mOverviewProxyService.getProxy() != null) {
- mOverviewProxyService.getProxy().onOverviewToggle();
- mOverviewProxyService.notifyToggleRecentApps();
+ if (mLauncherProxyService.getProxy() != null) {
+ mLauncherProxyService.getProxy().onOverviewToggle();
+ mLauncherProxyService.notifyToggleRecentApps();
}
} catch (RemoteException e) {
Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index 0488962fd076..80c7c4a07c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.data.repository
import com.android.compose.animation.scene.ContentKey
@@ -29,7 +27,6 @@ import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneDataSource
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index ba9dc7625769..8bc9d96c064a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -35,7 +35,6 @@ import com.android.systemui.scene.shared.model.Scenes
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -56,7 +55,6 @@ import kotlinx.coroutines.flow.update
* other feature modules should depend on and call into this class when their parts of the
* application state change.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class SceneInteractor
@Inject
@@ -149,7 +147,6 @@ constructor(
* their finger to transition between scenes, this value will be true while their finger is on
* the screen, then false for the rest of the transition.
*/
- @OptIn(ExperimentalCoroutinesApi::class)
val isTransitionUserInputOngoing: StateFlow<Boolean> =
transitionState
.flatMapLatest {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
index 3a07ce959bb3..79226138d07a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
@@ -36,7 +36,6 @@ import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataS
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
@@ -47,7 +46,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Business logic about the visibility of various parts of the window root view. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class WindowRootViewVisibilityInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt
index 6e79d568761f..140b231593bd 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.domain.resolver
import android.util.Log
@@ -33,7 +31,6 @@ import dagger.Module
import dagger.multibindings.IntoSet
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt
index 7939404251d1..4044381e25e7 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/KeyguardStateCallbackStartable.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.domain.startable
import android.os.DeadObjectException
@@ -35,7 +33,6 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 63c10c9b971a..8602884ec4ee 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.domain.startable
import android.app.StatusBarManager
@@ -67,6 +65,7 @@ import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.VibratorHelper
@@ -86,7 +85,6 @@ import java.io.PrintWriter
import java.util.Optional
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.SharingStarted
@@ -109,7 +107,6 @@ import kotlinx.coroutines.launch
* Hooks up business logic that manipulates the state of the [SceneInteractor] for the system UI
* scene container based on state from other systems.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class SceneContainerStartable
@Inject
@@ -147,6 +144,7 @@ constructor(
private val msdlPlayer: MSDLPlayer,
private val disabledContentInteractor: DisabledContentInteractor,
private val activityTransitionAnimator: ActivityTransitionAnimator,
+ private val shadeModeInteractor: ShadeModeInteractor,
) : CoreStartable {
private val centralSurfaces: CentralSurfaces?
get() = centralSurfacesOptLazy.get().getOrNull()
@@ -179,15 +177,52 @@ constructor(
}
}
- override fun dump(pw: PrintWriter, args: Array<out String>) =
- pw.asIndenting().run {
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ with(pw.asIndenting()) {
printSection("SceneContainerFlag") {
- println("isEnabled", SceneContainerFlag.isEnabled)
- printSection("requirementDescription") {
+ printSection("Framework availability") {
+ println("isEnabled", SceneContainerFlag.isEnabled)
println(SceneContainerFlag.requirementDescription())
}
+
+ if (!SceneContainerFlag.isEnabled) {
+ return
+ }
+
+ printSection("Scene state") {
+ println("currentScene", sceneInteractor.currentScene.value.debugName)
+ println(
+ "currentOverlays",
+ sceneInteractor.currentOverlays.value.joinToString(", ") { overlay ->
+ overlay.debugName
+ },
+ )
+ println("backStack", sceneBackInteractor.backStack.value)
+ println("shadeMode", shadeModeInteractor.shadeMode.value)
+ }
+
+ printSection("Authentication state") {
+ println("isKeyguardEnabled", keyguardEnabledInteractor.isKeyguardEnabled.value)
+ println(
+ "isUnlocked",
+ deviceUnlockedInteractor.deviceUnlockStatus.value.isUnlocked,
+ )
+ println("isDeviceEntered", deviceEntryInteractor.isDeviceEntered.value)
+ println(
+ "isFaceAuthEnabledAndEnrolled",
+ faceUnlockInteractor.isFaceAuthEnabledAndEnrolled(),
+ )
+ println("canSwipeToEnter", deviceEntryInteractor.canSwipeToEnter.value)
+ }
+
+ printSection("Power state") {
+ println("detailedWakefulness", powerInteractor.detailedWakefulness.value)
+ println("isDozing", keyguardInteractor.isDozing.value)
+ println("isAodAvailable", keyguardInteractor.isAodAvailable.value)
+ }
}
}
+ }
private fun resetShadeSessions() {
applicationScope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/ScrimStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/ScrimStartable.kt
index 1d970349b955..522dfabb8b61 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/ScrimStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/ScrimStartable.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.domain.startable
import androidx.annotation.VisibleForTesting
@@ -45,7 +43,6 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
index 1d8dc4f661da..7d09c457e8c1 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.domain.startable
import android.annotation.SuppressLint
@@ -50,7 +48,6 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import com.android.app.tracing.coroutines.launchTraced as launch
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
index 2bcd1d1a1e51..733b4210950f 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
@@ -89,8 +89,11 @@ object SceneContainerFlag {
@JvmStatic
fun requirementDescription(): String {
return buildString {
- getAllRequirements().forEach { requirement ->
- append('\n')
+ getAllRequirements().forEachIndexed { index, requirement ->
+ if (index > 0) {
+ append('\n')
+ }
+
append(if (requirement.isEnabled) " [MET]" else "[NOT MET]")
append(" ${requirement.name}")
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
index eb4c0f24c58a..5d0edc504782 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneDataSourceDelegator.kt
@@ -14,15 +14,12 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.shared.model
import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
index b8da2274eec1..0dd0e3dd87c6 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
@@ -14,11 +14,9 @@ import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.shade.TouchLogger
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import javax.inject.Provider
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
/** A root view of the main SysUI window that supports scenes. */
-@ExperimentalCoroutinesApi
class SceneWindowRootView(context: Context, attrs: AttributeSet?) : WindowRootView(context, attrs) {
private var motionEventHandler: SceneContainerViewModel.MotionEventHandler? = null
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 7da007c2fe53..ffc82688ec95 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -51,14 +51,12 @@ import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
-@ExperimentalCoroutinesApi
object SceneWindowRootViewBinder {
/** Binds between the view and view-model pertaining to a specific scene container. */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/BaseShadeControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/BaseShadeControllerImpl.kt
index 2fdcaa508941..b271c6979b31 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/BaseShadeControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/BaseShadeControllerImpl.kt
@@ -22,10 +22,8 @@ import com.android.systemui.statusbar.NotificationPresenter
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import dagger.Lazy
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** A base class for non-empty implementations of ShadeController. */
-@OptIn(ExperimentalCoroutinesApi::class)
abstract class BaseShadeControllerImpl(
protected val commandQueue: CommandQueue,
protected val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index a1b4def09ba9..28f5694c3332 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -2251,7 +2251,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
private boolean isPanelVisibleBecauseOfHeadsUp() {
- boolean headsUpVisible = mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway;
+ boolean headsUpVisible = (mHeadsUpManager != null && mHeadsUpManager.hasPinnedHeadsUp())
+ || mHeadsUpAnimatingAway;
return headsUpVisible && mBarState == StatusBarState.SHADE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index ffec8f284c48..10a9fd20ee5a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -45,6 +45,7 @@ import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags;
import com.android.systemui.bouncer.ui.binder.BouncerViewBinder;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlagsClassic;
@@ -87,6 +88,7 @@ import com.android.systemui.util.time.SystemClock;
import com.android.systemui.window.ui.WindowRootViewBinder;
import com.android.systemui.window.ui.viewmodel.WindowRootViewModel;
+import kotlinx.coroutines.CoroutineDispatcher;
import kotlinx.coroutines.ExperimentalCoroutinesApi;
import kotlinx.coroutines.flow.Flow;
@@ -120,6 +122,7 @@ public class NotificationShadeWindowViewController implements Dumpable {
private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final QuickSettingsController mQuickSettingsController;
+ private final CoroutineDispatcher mMainDispatcher;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final GlanceableHubContainerController
mGlanceableHubContainerController;
@@ -165,7 +168,6 @@ public class NotificationShadeWindowViewController implements Dumpable {
};
private final SystemClock mClock;
- @ExperimentalCoroutinesApi
@Inject
public NotificationShadeWindowViewController(
BlurUtils blurUtils,
@@ -206,7 +208,8 @@ public class NotificationShadeWindowViewController implements Dumpable {
AlternateBouncerInteractor alternateBouncerInteractor,
BouncerViewBinder bouncerViewBinder,
@ShadeDisplayAware Provider<ConfigurationForwarder> configurationForwarder,
- BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor) {
+ BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor,
+ @Main CoroutineDispatcher mainDispatcher) {
mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
mStatusBarStateController = statusBarStateController;
@@ -234,6 +237,7 @@ public class NotificationShadeWindowViewController implements Dumpable {
mPrimaryBouncerInteractor = primaryBouncerInteractor;
mAlternateBouncerInteractor = alternateBouncerInteractor;
mQuickSettingsController = quickSettingsController;
+ mMainDispatcher = mainDispatcher;
// This view is not part of the newly inflated expanded status bar.
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -288,7 +292,7 @@ public class NotificationShadeWindowViewController implements Dumpable {
if (SceneContainerFlag.isEnabled()) return;
WindowRootViewBinder.INSTANCE.bind(mView, windowRootViewModelFactory, blurUtils,
- choreographer);
+ choreographer, mMainDispatcher);
}
private void bindBouncer(BouncerViewBinder bouncerViewBinder) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
index 7299f092640f..cf310dd32613 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
@@ -34,8 +34,8 @@ import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.plugins.qs.QS
import com.android.systemui.plugins.qs.QSContainerController
-import com.android.systemui.recents.OverviewProxyService
-import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
+import com.android.systemui.recents.LauncherProxyService
+import com.android.systemui.recents.LauncherProxyService.LauncherProxyListener
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shared.system.QuickStepContract
@@ -57,7 +57,7 @@ class NotificationsQSContainerController
constructor(
view: NotificationsQuickSettingsContainer,
private val navigationModeController: NavigationModeController,
- private val overviewProxyService: OverviewProxyService,
+ private val launcherProxyService: LauncherProxyService,
private val shadeHeaderController: ShadeHeaderController,
private val shadeInteractor: ShadeInteractor,
private val fragmentService: FragmentService,
@@ -85,8 +85,8 @@ constructor(
private var isGestureNavigation = true
private var taskbarVisible = false
- private val taskbarVisibilityListener: OverviewProxyListener =
- object : OverviewProxyListener {
+ private val taskbarVisibilityListener: LauncherProxyListener =
+ object : LauncherProxyListener {
override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) {
taskbarVisible = visible
}
@@ -134,7 +134,7 @@ constructor(
public override fun onViewAttached() {
updateResources()
- overviewProxyService.addCallback(taskbarVisibilityListener)
+ launcherProxyService.addCallback(taskbarVisibilityListener)
mView.setInsetsChangedListener(delayedInsetSetter)
mView.setQSFragmentAttachedListener { qs: QS -> qs.setContainerController(this) }
mView.setConfigurationChangedListener { updateResources() }
@@ -142,7 +142,7 @@ constructor(
}
override fun onViewDetached() {
- overviewProxyService.removeCallback(taskbarVisibilityListener)
+ launcherProxyService.removeCallback(taskbarVisibilityListener)
mView.removeOnInsetsChangedListener()
mView.removeQSFragmentAttachedListener()
mView.setConfigurationChangedListener(null)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
index 5b06ad2d1453..e6834ad6cdda 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
@@ -37,7 +37,6 @@ import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
@@ -47,7 +46,6 @@ import kotlinx.coroutines.withContext
*
* TODO(b/300258424) rename to ShadeControllerImpl and inline/delete all the deprecated methods
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class ShadeControllerSceneImpl
@Inject
@@ -194,7 +192,6 @@ constructor(
}
}
- @ExperimentalCoroutinesApi
override fun collapseShadeForActivityStart() {
if (shadeInteractor.isAnyExpanded.value) {
animateCollapseShadeForcedDelayed()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index d82f8e722744..9a79e1a45505 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter
import android.annotation.IdRes
import android.app.PendingIntent
import android.app.StatusBarManager
+import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Insets
@@ -58,6 +59,7 @@ import com.android.systemui.shade.ShadeViewProviderModule.Companion.SHADE_HEADER
import com.android.systemui.shade.carrier.ShadeCarrierGroup
import com.android.systemui.shade.carrier.ShadeCarrierGroupController
import com.android.systemui.shade.data.repository.ShadeDisplaysRepository
+import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStore
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
@@ -70,6 +72,7 @@ import com.android.systemui.statusbar.policy.NextAlarmController
import com.android.systemui.statusbar.policy.VariableDateView
import com.android.systemui.statusbar.policy.VariableDateViewController
import com.android.systemui.util.ViewController
+import dagger.Lazy
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Named
@@ -93,7 +96,8 @@ constructor(
private val privacyIconsController: HeaderPrivacyIconsController,
private val statusBarContentInsetsProviderStore: StatusBarContentInsetsProviderStore,
@ShadeDisplayAware private val configurationController: ConfigurationController,
- private val shadeDisplaysRepository: ShadeDisplaysRepository,
+ @ShadeDisplayAware private val context: Context,
+ private val shadeDisplaysRepositoryLazy: Lazy<ShadeDisplaysRepository>,
private val variableDateViewControllerFactory: VariableDateViewController.Factory,
@Named(SHADE_HEADER) private val batteryMeterViewController: BatteryMeterViewController,
private val dumpManager: DumpManager,
@@ -108,7 +112,15 @@ constructor(
private val statusBarContentInsetsProvider
get() =
- statusBarContentInsetsProviderStore.forDisplay(shadeDisplaysRepository.displayId.value)
+ statusBarContentInsetsProviderStore.forDisplay(
+ if (ShadeWindowGoesAround.isEnabled) {
+ // ShadeDisplaysRepository is the source of truth for display id when
+ // ShadeWindowGoesAround.isEnabled
+ shadeDisplaysRepositoryLazy.get().displayId.value
+ } else {
+ context.displayId
+ }
+ )
companion object {
/** IDs for transitions and constraints for the [MotionLayout]. */
@@ -293,7 +305,7 @@ constructor(
override fun onDensityOrFontScaleChanged() {
clock.setTextAppearance(R.style.TextAppearance_QS_Status)
date.setTextAppearance(R.style.TextAppearance_QS_Status)
- mShadeCarrierGroup.updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
+ mShadeCarrierGroup.updateTextAppearance(R.style.TextAppearance_QS_Status)
loadConstraints()
header.minHeight =
resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index 3449e81a4630..55ee27d1027c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.shade
import android.annotation.SuppressLint
@@ -62,7 +60,6 @@ import dagger.Module
import dagger.Provides
import javax.inject.Named
import javax.inject.Provider
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Module for providing views related to the shade. */
@Module
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt
index f959f7fe0c31..4eb707297073 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt
@@ -27,7 +27,6 @@ import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -48,7 +47,6 @@ interface ShadeDisplaysRepository {
/** Keeps the policy and propagates the display id for the shade from it. */
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
class ShadeDisplaysRepositoryImpl
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt
index dfdf2ad564db..35209488a7ee 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt
@@ -14,12 +14,9 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.shade.domain.interactor
import com.android.systemui.dagger.SysUISingleton
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
index cea521f094be..c447a190d699 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.shade.domain.interactor
import com.android.compose.animation.scene.ContentKey
@@ -26,7 +24,6 @@ import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.SysuiStatusBarStateController
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
index 8467185b4239..615c2fd7258a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorSceneContainerImpl.kt
@@ -24,7 +24,6 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.ShadeAnimationRepository
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
@@ -36,7 +35,6 @@ import kotlinx.coroutines.flow.stateIn
@SysUISingleton
class ShadeAnimationInteractorSceneContainerImpl
@Inject
-@OptIn(ExperimentalCoroutinesApi::class)
constructor(
@Background scope: CoroutineScope,
shadeAnimationRepository: ShadeAnimationRepository,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
index 884cfc10678d..5a63034b5754 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
@@ -22,10 +22,8 @@ import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/** Implementation of ShadeBackActionInteractor backed by scenes. */
-@OptIn(ExperimentalCoroutinesApi::class)
class ShadeBackActionInteractorImpl
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
index 992385c8d80e..661f2ae5132c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
@@ -35,7 +35,6 @@ import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -46,7 +45,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** ShadeInteractor implementation for Scene Container. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class ShadeInteractorSceneContainerImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
index 0253122183eb..7fd0e4e9d468 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.shade.ui.viewmodel
import androidx.lifecycle.LifecycleOwner
@@ -35,7 +33,6 @@ import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.util.concurrent.atomic.AtomicBoolean
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
index 2544323d83d5..79a872edd2c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
@@ -573,13 +573,13 @@ public final class KeyboardShortcutListSearch {
Pair.create(KeyEvent.KEYCODE_ESCAPE, KeyEvent.META_META_ON),
Pair.create(KeyEvent.KEYCODE_DEL, KeyEvent.META_META_ON),
Pair.create(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_META_ON))),
- /* Take a full screenshot: Meta + Ctrl + S */
+ /* Take a full screenshot: Meta + S */
new ShortcutKeyGroupMultiMappingInfo(
context.getString(R.string.group_system_full_screenshot),
Arrays.asList(
Pair.create(
KeyEvent.KEYCODE_S,
- KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON))),
+ KeyEvent.META_META_ON))),
/* Access list of system / apps shortcuts: Meta + / */
new ShortcutKeyGroupMultiMappingInfo(
context.getString(R.string.group_system_access_system_app_shortcuts),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index c8f972774ab0..382fc7058bf0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -70,7 +70,7 @@ import com.android.systemui.flags.FeatureFlagsClassic;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -152,7 +152,7 @@ public class NotificationLockscreenUserManagerImpl implements
private final List<UserChangedListener> mListeners = new ArrayList<>();
private final BroadcastDispatcher mBroadcastDispatcher;
private final NotificationClickNotifier mClickNotifier;
- private final Lazy<OverviewProxyService> mOverviewProxyServiceLazy;
+ private final Lazy<LauncherProxyService> mLauncherProxyServiceLazy;
private final FeatureFlagsClassic mFeatureFlags;
private boolean mShowLockscreenNotifications;
private LockPatternUtils mLockPatternUtils;
@@ -235,8 +235,8 @@ public class NotificationLockscreenUserManagerImpl implements
if (!keyguardPrivateNotifications()) {
// Start the overview connection to the launcher service
// Connect if user hasn't connected yet
- if (mOverviewProxyServiceLazy.get().getProxy() == null) {
- mOverviewProxyServiceLazy.get().startConnectionToCurrentUser();
+ if (mLauncherProxyServiceLazy.get().getProxy() == null) {
+ mLauncherProxyServiceLazy.get().startConnectionToCurrentUser();
}
}
} else if (Objects.equals(action, NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION)) {
@@ -318,7 +318,7 @@ public class NotificationLockscreenUserManagerImpl implements
Lazy<NotificationVisibilityProvider> visibilityProviderLazy,
Lazy<CommonNotifCollection> commonNotifCollectionLazy,
NotificationClickNotifier clickNotifier,
- Lazy<OverviewProxyService> overviewProxyServiceLazy,
+ Lazy<LauncherProxyService> launcherProxyServiceLazy,
KeyguardManager keyguardManager,
StatusBarStateController statusBarStateController,
@Main Executor mainExecutor,
@@ -343,7 +343,7 @@ public class NotificationLockscreenUserManagerImpl implements
mVisibilityProviderLazy = visibilityProviderLazy;
mCommonNotifCollectionLazy = commonNotifCollectionLazy;
mClickNotifier = clickNotifier;
- mOverviewProxyServiceLazy = overviewProxyServiceLazy;
+ mLauncherProxyServiceLazy = launcherProxyServiceLazy;
statusBarStateController.addCallback(this);
mLockPatternUtils = lockPatternUtils;
mKeyguardManager = keyguardManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index ca2fbdd1cdd9..a2a840942f3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -54,7 +54,6 @@ import com.android.systemui.statusbar.policy.SplitShadeStateController
import com.android.systemui.util.WallpaperController
import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
import com.android.wm.shell.appzoomout.AppZoomOut
-
import java.io.PrintWriter
import java.util.Optional
import javax.inject.Inject
@@ -280,9 +279,7 @@ constructor(
wallpaperController.setNotificationShadeZoom(zoomOutFromShadeRadius)
if (spatialModelAppPushback()) {
appZoomOutOptional.ifPresent { appZoomOut ->
- appZoomOut.setProgress(
- zoomOutFromShadeRadius
- )
+ appZoomOut.setProgress(zoomOutFromShadeRadius)
}
}
listeners.forEach {
@@ -526,7 +523,7 @@ constructor(
private fun scheduleUpdate() {
val (blur, zoomOutFromShadeRadius) = computeBlurAndZoomOut()
zoomOutCalculatedFromShadeRadius = zoomOutFromShadeRadius
- if (Flags.bouncerUiRevamp()) {
+ if (Flags.bouncerUiRevamp() || Flags.glanceableHubBlurredBackground()) {
updateScheduled =
windowRootViewBlurInteractor.requestBlurForShade(blur, shouldBlurBeOpaque)
return
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt
index 836cf49d4d63..cece52110567 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt
@@ -27,7 +27,6 @@ import com.android.systemui.statusbar.notification.shared.ActiveNotificationMode
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
@@ -45,7 +44,6 @@ import kotlinx.coroutines.flow.map
*
* @property creationTime the time when the notification first appeared as promoted.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
class SingleNotificationChipInteractor
@AssistedInject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt
index 4fad01d9f448..9463db57585b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt
@@ -33,7 +33,6 @@ import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -46,7 +45,6 @@ import kotlinx.coroutines.flow.map
/** An interactor for the notification chips shown in the status bar. */
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
class StatusBarNotificationChipsInteractor
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
index b7cad625b7b8..46456b841e3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
@@ -30,6 +30,7 @@ import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNoti
import com.android.systemui.statusbar.notification.domain.model.TopPinnedState
import com.android.systemui.statusbar.notification.headsup.PinnedStatus
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -73,17 +74,24 @@ constructor(
OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon(this.key)
}
val colors = this.promotedContent.toCustomColorsModel()
- val onClickListener =
+
+ val clickListener: () -> Unit = {
+ // The notification pipeline needs everything to run on the main thread, so keep
+ // this event on the main thread.
+ applicationScope.launch {
+ notifChipsInteractor.onPromotedNotificationChipTapped(this@toActivityChipModel.key)
+ }
+ }
+ val onClickListenerLegacy =
View.OnClickListener {
- // The notification pipeline needs everything to run on the main thread, so keep
- // this event on the main thread.
- applicationScope.launch {
- notifChipsInteractor.onPromotedNotificationChipTapped(
- this@toActivityChipModel.key
- )
- }
+ StatusBarChipsModernization.assertInLegacyMode()
+ clickListener.invoke()
}
- val clickBehavior = OngoingActivityChipModel.ClickBehavior.None
+ val clickBehavior =
+ OngoingActivityChipModel.ClickBehavior.ShowHeadsUpNotification({
+ StatusBarChipsModernization.assertInNewMode()
+ clickListener.invoke()
+ })
val isShowingHeadsUpFromChipTap =
headsUpState is TopPinnedState.Pinned &&
@@ -95,7 +103,7 @@ constructor(
return OngoingActivityChipModel.Shown.IconOnly(
icon,
colors,
- onClickListener,
+ onClickListenerLegacy,
clickBehavior,
)
}
@@ -105,7 +113,7 @@ constructor(
icon,
colors,
this.promotedContent.shortCriticalText,
- onClickListener,
+ onClickListenerLegacy,
clickBehavior,
)
}
@@ -121,7 +129,7 @@ constructor(
return OngoingActivityChipModel.Shown.IconOnly(
icon,
colors,
- onClickListener,
+ onClickListenerLegacy,
clickBehavior,
)
}
@@ -130,7 +138,7 @@ constructor(
return OngoingActivityChipModel.Shown.IconOnly(
icon,
colors,
- onClickListener,
+ onClickListenerLegacy,
clickBehavior,
)
}
@@ -140,7 +148,7 @@ constructor(
icon,
colors,
time = this.promotedContent.time.time,
- onClickListener,
+ onClickListenerLegacy,
clickBehavior,
)
}
@@ -149,7 +157,7 @@ constructor(
icon,
colors,
startTimeMs = this.promotedContent.time.time,
- onClickListener,
+ onClickListenerLegacy,
clickBehavior,
)
}
@@ -159,7 +167,7 @@ constructor(
icon,
colors,
startTimeMs = this.promotedContent.time.time,
- onClickListener,
+ onClickListenerLegacy,
clickBehavior,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt
index 0b5e669b5fca..572c7faf19e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt
@@ -31,7 +31,6 @@ import com.android.systemui.statusbar.chips.StatusBarChipsLog
import com.android.systemui.statusbar.chips.screenrecord.domain.model.ScreenRecordChipModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -43,7 +42,6 @@ import kotlinx.coroutines.launch
/** Interactor for the screen recording chip shown in the status bar. */
@SysUISingleton
-@OptIn(ExperimentalCoroutinesApi::class)
class ScreenRecordChipInteractor
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
new file mode 100644
index 000000000000..13f4e51f2ba2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.chips.ui.compose
+
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.node.LayoutModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.constrain
+import androidx.compose.ui.unit.dp
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
+import com.android.systemui.statusbar.chips.ui.viewmodel.rememberChronometerState
+
+@Composable
+fun ChipContent(viewModel: OngoingActivityChipModel.Shown, modifier: Modifier = Modifier) {
+ val context = LocalContext.current
+ val isTextOnly = viewModel.icon == null
+ val hasEmbeddedIcon =
+ viewModel.icon is OngoingActivityChipModel.ChipIcon.StatusBarView ||
+ viewModel.icon is OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon
+ val startPadding =
+ if (isTextOnly || hasEmbeddedIcon) {
+ 0.dp
+ } else {
+ dimensionResource(id = R.dimen.ongoing_activity_chip_icon_text_padding)
+ }
+ val endPadding =
+ if (hasEmbeddedIcon) {
+ dimensionResource(
+ id = R.dimen.ongoing_activity_chip_text_end_padding_for_embedded_padding_icon
+ )
+ } else {
+ 0.dp
+ }
+ val textStyle = MaterialTheme.typography.labelLarge
+ val textColor = Color(viewModel.colors.text(context))
+ when (viewModel) {
+ is OngoingActivityChipModel.Shown.Timer -> {
+ val timerState = rememberChronometerState(startTimeMillis = viewModel.startTimeMs)
+ Text(
+ text = timerState.currentTimeText,
+ style = textStyle,
+ color = textColor,
+ modifier =
+ modifier.padding(start = startPadding, end = endPadding).neverDecreaseWidth(),
+ )
+ }
+
+ is OngoingActivityChipModel.Shown.Countdown -> {
+ ChipText(
+ text = viewModel.secondsUntilStarted.toString(),
+ style = textStyle,
+ color = textColor,
+ modifier =
+ modifier.padding(start = startPadding, end = endPadding).neverDecreaseWidth(),
+ backgroundColor = Color(viewModel.colors.background(context).defaultColor),
+ )
+ }
+
+ is OngoingActivityChipModel.Shown.Text -> {
+ ChipText(
+ text = viewModel.text,
+ style = textStyle,
+ color = textColor,
+ modifier = modifier.padding(start = startPadding, end = endPadding),
+ backgroundColor = Color(viewModel.colors.background(context).defaultColor),
+ )
+ }
+
+ is OngoingActivityChipModel.Shown.ShortTimeDelta -> {
+ // TODO(b/372657935): Implement ShortTimeDelta content in compose.
+ }
+ }
+}
+
+/** A modifier that ensures the width of the content only increases and never decreases. */
+private fun Modifier.neverDecreaseWidth(): Modifier {
+ return this.then(neverDecreaseWidthElement)
+}
+
+private data object neverDecreaseWidthElement : ModifierNodeElement<NeverDecreaseWidthNode>() {
+ override fun create(): NeverDecreaseWidthNode {
+ return NeverDecreaseWidthNode()
+ }
+
+ override fun update(node: NeverDecreaseWidthNode) {
+ error("This should never be called")
+ }
+}
+
+private class NeverDecreaseWidthNode : Modifier.Node(), LayoutModifierNode {
+ private var minWidth = 0
+
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints,
+ ): MeasureResult {
+ val placeable = measurable.measure(Constraints(minWidth = minWidth).constrain(constraints))
+ val width = placeable.width
+ val height = placeable.height
+
+ minWidth = maxOf(minWidth, width)
+
+ return layout(width, height) { placeable.place(0, 0) }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
index a682f9674e2e..647f3bd469f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
@@ -29,8 +29,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -45,10 +43,8 @@ import com.android.compose.animation.Expandable
import com.android.systemui.animation.Expandable
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.res.R
-import com.android.systemui.statusbar.chips.ui.compose.modifiers.neverDecreaseWidth
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
-import com.android.systemui.statusbar.chips.ui.viewmodel.rememberChronometerState
@Composable
fun OngoingActivityChip(model: OngoingActivityChipModel.Shown, modifier: Modifier = Modifier) {
@@ -66,6 +62,9 @@ fun OngoingActivityChip(model: OngoingActivityChipModel.Shown, modifier: Modifie
ChipBody(model, onClick = { clickBehavior.onClick(expandable) })
}
}
+ is OngoingActivityChipModel.ClickBehavior.ShowHeadsUpNotification -> {
+ ChipBody(model, onClick = { clickBehavior.onClick() })
+ }
is OngoingActivityChipModel.ClickBehavior.None -> {
ChipBody(model, modifier = modifier)
@@ -120,32 +119,8 @@ private fun ChipBody(
model.icon?.let { ChipIcon(viewModel = it, colors = model.colors) }
val isIconOnly = model is OngoingActivityChipModel.Shown.IconOnly
- val isTextOnly = model.icon == null
if (!isIconOnly) {
- ChipContent(
- viewModel = model,
- modifier =
- Modifier.padding(
- start =
- if (isTextOnly || hasEmbeddedIcon) {
- 0.dp
- } else {
- dimensionResource(
- id = R.dimen.ongoing_activity_chip_icon_text_padding
- )
- },
- end =
- if (hasEmbeddedIcon) {
- dimensionResource(
- id =
- R.dimen
- .ongoing_activity_chip_text_end_padding_for_embedded_padding_icon
- )
- } else {
- 0.dp
- },
- ),
- )
+ ChipContent(viewModel = model)
}
}
}
@@ -193,46 +168,6 @@ private fun ChipIcon(
}
@Composable
-private fun ChipContent(viewModel: OngoingActivityChipModel.Shown, modifier: Modifier = Modifier) {
- val context = LocalContext.current
- when (viewModel) {
- is OngoingActivityChipModel.Shown.Timer -> {
- val timerState = rememberChronometerState(startTimeMillis = viewModel.startTimeMs)
- Text(
- text = timerState.currentTimeText,
- style = MaterialTheme.typography.labelLarge,
- color = Color(viewModel.colors.text(context)),
- modifier = modifier.neverDecreaseWidth(),
- )
- }
-
- is OngoingActivityChipModel.Shown.Countdown -> {
- ChipText(
- text = viewModel.secondsUntilStarted.toString(),
- color = Color(viewModel.colors.text(context)),
- style = MaterialTheme.typography.labelLarge,
- modifier = modifier.neverDecreaseWidth(),
- backgroundColor = Color(viewModel.colors.background(context).defaultColor),
- )
- }
-
- is OngoingActivityChipModel.Shown.Text -> {
- ChipText(
- text = viewModel.text,
- color = Color(viewModel.colors.text(context)),
- style = MaterialTheme.typography.labelLarge,
- modifier = modifier,
- backgroundColor = Color(viewModel.colors.background(context).defaultColor),
- )
- }
-
- is OngoingActivityChipModel.Shown.ShortTimeDelta -> {
- // TODO(b/372657935): Implement ShortTimeDelta content in compose.
- }
- }
-}
-
-@Composable
private fun ExpandableChip(
color: () -> Color,
shape: Shape,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt
deleted file mode 100644
index 505a5fcb18b4..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2025 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.chips.ui.compose.modifiers
-
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.Measurable
-import androidx.compose.ui.layout.MeasureResult
-import androidx.compose.ui.layout.MeasureScope
-import androidx.compose.ui.node.LayoutModifierNode
-import androidx.compose.ui.node.ModifierNodeElement
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.constrain
-
-/** A modifier that ensures the width of the content only increases and never decreases. */
-fun Modifier.neverDecreaseWidth(): Modifier {
- return this.then(neverDecreaseWidthElement)
-}
-
-private data object neverDecreaseWidthElement : ModifierNodeElement<NeverDecreaseWidthNode>() {
- override fun create(): NeverDecreaseWidthNode {
- return NeverDecreaseWidthNode()
- }
-
- override fun update(node: NeverDecreaseWidthNode) {
- error("This should never be called")
- }
-}
-
-private class NeverDecreaseWidthNode : Modifier.Node(), LayoutModifierNode {
- private var minWidth = 0
-
- override fun MeasureScope.measure(
- measurable: Measurable,
- constraints: Constraints,
- ): MeasureResult {
- val placeable = measurable.measure(Constraints(minWidth = minWidth).constrain(constraints))
- val width = placeable.width
- val height = placeable.height
-
- minWidth = maxOf(minWidth, width)
-
- return layout(width, height) { placeable.place(0, 0) }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
index 68c8f8cb4254..c6d6da2ad9aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt
@@ -170,5 +170,8 @@ sealed class OngoingActivityChipModel {
/** The chip expands into a dialog or activity on click. */
data class ExpandAction(val onClick: (Expandable) -> Unit) : ClickBehavior
+
+ /** Clicking the chip will show the heads up notification associated with the chip. */
+ data class ShowHeadsUpNotification(val onClick: () -> Unit) : ClickBehavior
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelper.kt
index c8507093649b..823b910ca13b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelper.kt
@@ -20,7 +20,6 @@ import android.annotation.SuppressLint
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -41,7 +40,6 @@ import com.android.app.tracing.coroutines.launchTraced as launch
* this class helps us immediately hide the chip as soon as the user clicks "Stop" in the dialog.
* See b/353249803#comment4.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
class ChipTransitionHelper(@Application private val scope: CoroutineScope) {
/** A flow that emits each time the user has clicked "Stop" on the dialog. */
@SuppressLint("SharedFlowCreation")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index 3825c098ca5d..b6ef95893036 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification
import android.app.Notification
+import android.app.Notification.EXTRA_SUMMARIZED_CONTENT
import android.content.Context
import android.content.pm.LauncherApps
import android.graphics.drawable.AnimatedImageDrawable
@@ -66,6 +67,12 @@ constructor(
messagingStyle.shortcutIcon = launcherApps.getShortcutIcon(shortcutInfo)
shortcutInfo.label?.let { label -> messagingStyle.conversationTitle = label }
}
+ if (NmSummarizationUiFlag.isEnabled) {
+ entry.sbn.notification.extras.putCharSequence(
+ EXTRA_SUMMARIZED_CONTENT, entry.ranking.summarization
+ )
+ }
+
messagingStyle.unreadMessageCount =
conversationNotificationManager.getUnreadCount(entry, recoveredBuilder)
return messagingStyle
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NmSummarizationUiFlag.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NmSummarizationUiFlag.kt
new file mode 100644
index 000000000000..feac0a514828
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NmSummarizationUiFlag.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.app.Flags;
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/**
+ * Helper for android.app.nm_summarization and android.nm_summarization_ui. The new functionality
+ * should be enabled if either flag is enabled.
+ */
+@Suppress("NOTHING_TO_INLINE")
+object NmSummarizationUiFlag {
+ const val FLAG_DESC = "android.app.nm_summarization(_ui)"
+
+ @JvmStatic
+ inline val isEnabled
+ get() = Flags.nmSummarizationUi() || Flags.nmSummarization()
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This protects users from the
+ * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+ * build to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_DESC)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInLegacyMode() =
+ RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_DESC)
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
index 1875e7e46693..90916d1c77d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.statusbar.notification.collection.coordinator
import android.app.Notification
@@ -48,7 +46,6 @@ import dagger.Binds
import dagger.Module
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.mapNotNull
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
index 331ef1c01596..aa5008b8416e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
@@ -40,6 +40,7 @@ internal constructor(
@RedactionType val redactionType: Int,
val isChildInGroup: Boolean,
val isGroupSummary: Boolean,
+ val summarization: String?,
) {
companion object {
@JvmStatic
@@ -61,6 +62,7 @@ internal constructor(
AsyncGroupHeaderViewInflation.isEnabled &&
!oldAdjustment.isGroupSummary &&
newAdjustment.isGroupSummary -> true
+ oldAdjustment.summarization != newAdjustment.summarization -> true
else -> false
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
index 97e55c19d2f4..465bc288cbc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
@@ -152,5 +152,6 @@ constructor(
},
isChildInGroup = entry.hasEverBeenGroupChild(),
isGroupSummary = entry.hasEverBeenGroupSummary(),
+ summarization = entry.ranking.summarization
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 0346108856a2..3dbf0698dce9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -27,6 +27,7 @@ import com.android.settingslib.notification.data.repository.ZenModeRepositoryImp
import com.android.settingslib.notification.domain.interactor.NotificationsSoundPolicyInteractor;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.android.systemui.CoreStartable;
+import com.android.systemui.Flags;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.dagger.qualifiers.Background;
@@ -84,6 +85,8 @@ import com.android.systemui.statusbar.notification.row.NotificationEntryProcesso
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
import com.android.systemui.statusbar.notification.row.ui.viewmodel.ActivatableNotificationViewModelModule;
+import com.android.systemui.statusbar.notification.stack.MagneticNotificationRowManager;
+import com.android.systemui.statusbar.notification.stack.MagneticNotificationRowManagerImpl;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
@@ -322,4 +325,19 @@ public interface NotificationsModule {
return (entry, recoveredBuilder) -> null;
}
}
+
+ /**
+ * Provide an implementation of {@link MagneticNotificationRowManager} based on its flag.
+ */
+ @Provides
+ @SysUISingleton
+ static MagneticNotificationRowManager provideMagneticNotificationRowManager(
+ Provider<MagneticNotificationRowManagerImpl> implProvider
+ ) {
+ if (Flags.magneticNotificationSwipes()) {
+ return implProvider.get();
+ } else {
+ return MagneticNotificationRowManager.getEmpty();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
index 6140c92369b3..cdbe0fd23a9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.statusbar.notification.domain.interactor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
@@ -29,7 +27,6 @@ import com.android.systemui.statusbar.notification.domain.model.TopPinnedState
import com.android.systemui.statusbar.notification.headsup.PinnedStatus
import com.android.systemui.statusbar.notification.shared.HeadsUpRowKey
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
index 7e2361f24da9..fa0cea15c43f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel
import android.content.Context
import android.icu.text.MessageFormat
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
import com.android.systemui.modes.shared.ModesUi
@@ -36,9 +37,11 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
/**
* ViewModel for the empty shade (aka the "No notifications" text shown when there are no
@@ -51,6 +54,7 @@ constructor(
zenModeInteractor: ZenModeInteractor,
seenNotificationsInteractor: SeenNotificationsInteractor,
notificationSettingsInteractor: NotificationSettingsInteractor,
+ configurationInteractor: ConfigurationInteractor,
@Background bgDispatcher: CoroutineDispatcher,
dumpManager: DumpManager,
) : FlowDumperImpl(dumpManager) {
@@ -71,6 +75,13 @@ constructor(
"hasFilteredOutSeenNotifications"
)
+ private val primaryLocale by lazy {
+ configurationInteractor.configurationValues
+ .map { it.locales.get(0) ?: Locale.getDefault() }
+ .onStart { emit(Locale.getDefault()) }
+ .distinctUntilChanged()
+ }
+
val text: Flow<String> by lazy {
if (ModesEmptyShadeFix.isUnexpectedlyInLegacyMode()) {
flowOf(context.getString(R.string.empty_shade_text))
@@ -79,14 +90,16 @@ constructor(
// recommended architecture, and making it so it reacts to changes for the new Modes.
// The former does not depend on the modes flags being on, but the latter does.
if (ModesUi.isEnabled) {
- zenModeInteractor.modesHidingNotifications.map { modes ->
+ combine(zenModeInteractor.modesHidingNotifications, primaryLocale) {
+ modes,
+ locale ->
// Create a string that is either "No notifications" if no modes are
- // filtering
- // them out, or something like "Notifications paused by SomeMode" otherwise.
+ // filtering them out, or something like "Notifications paused by SomeMode"
+ // otherwise.
val msgFormat =
MessageFormat(
context.getString(R.string.modes_suppressing_shade_text),
- Locale.getDefault(),
+ locale,
)
val count = modes.count()
val args: MutableMap<String, Any> = HashMap()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
index b913355ea59b..f02edee399eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
@@ -13,8 +13,6 @@
*
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.statusbar.notification.icon.domain.interactor
import com.android.systemui.dagger.qualifiers.Background
@@ -29,7 +27,6 @@ import java.util.Optional
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.optionals.getOrNull
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
index 664b2afe90b4..cb9bd4a3fd35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
@@ -31,6 +31,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.isVisible
+import com.android.app.tracing.traceSection
import com.android.internal.R
import com.android.internal.widget.BigPictureNotificationImageView
import com.android.internal.widget.CachingIconView
@@ -51,44 +52,57 @@ fun AODPromotedNotification(viewModelFactory: AODPromotedNotificationViewModel.F
return
}
- val viewModel =
- rememberViewModel(traceName = "AODPromotedNotification") { viewModelFactory.create() }
+ val viewModel = rememberViewModel(traceName = "$TAG.viewModel") { viewModelFactory.create() }
val content = viewModel.content ?: return
key(content.identity) {
+ val layoutResource = content.layoutResource ?: return
+
AndroidView(
factory = { context ->
- LayoutInflater.from(context)
- .inflate(content.layoutResource, /* root= */ null)
- .apply { setTag(viewUpdaterTagId, AODPromotedNotificationViewUpdater(this)) }
+ traceSection("$TAG.inflate") {
+ LayoutInflater.from(context).inflate(layoutResource, /* root= */ null)
+ }
+ .apply {
+ setTag(
+ viewUpdaterTagId,
+ traceSection("$TAG.findViews") {
+ AODPromotedNotificationViewUpdater(this)
+ },
+ )
+ }
},
update = { view ->
- (view.getTag(viewUpdaterTagId) as AODPromotedNotificationViewUpdater).update(
- content
- )
+ traceSection("$TAG.update") {
+ (view.getTag(viewUpdaterTagId) as AODPromotedNotificationViewUpdater).update(
+ content
+ )
+ }
},
)
}
}
-private val PromotedNotificationContentModel.layoutResource: Int
+private val PromotedNotificationContentModel.layoutResource: Int?
get() {
return if (Flags.notificationsRedesignTemplates()) {
when (style) {
+ Style.Base -> R.layout.notification_2025_template_expanded_base
Style.BigPicture -> R.layout.notification_2025_template_expanded_big_picture
Style.BigText -> R.layout.notification_2025_template_expanded_big_text
Style.Call -> R.layout.notification_2025_template_expanded_call
Style.Progress -> R.layout.notification_2025_template_expanded_progress
- Style.Ineligible -> 0
+ Style.Ineligible -> null
}
} else {
when (style) {
+ Style.Base -> R.layout.notification_template_material_big_base
Style.BigPicture -> R.layout.notification_template_material_big_picture
Style.BigText -> R.layout.notification_template_material_big_text
Style.Call -> R.layout.notification_template_material_big_call
Style.Progress -> R.layout.notification_template_material_progress
- Style.Ineligible -> 0
+ Style.Ineligible -> null
}
}
}
@@ -131,6 +145,7 @@ private class AODPromotedNotificationViewUpdater(root: View) {
fun update(content: PromotedNotificationContentModel) {
when (content.style) {
+ Style.Base -> updateBase(content)
Style.BigPicture -> updateBigPicture(content)
Style.BigText -> updateBigText(content)
Style.Call -> updateCall(content)
@@ -139,20 +154,24 @@ private class AODPromotedNotificationViewUpdater(root: View) {
}
}
- private fun updateBigPicture(content: PromotedNotificationContentModel) {
+ private fun updateBase(
+ content: PromotedNotificationContentModel,
+ textView: ImageFloatingTextView? = null,
+ ) {
updateHeader(content)
updateTitle(title, content)
- updateText(text, content)
+ updateText(textView ?: text, content)
+ }
+
+ private fun updateBigPicture(content: PromotedNotificationContentModel) {
+ updateBase(content)
bigPicture?.visibility = GONE
}
private fun updateBigText(content: PromotedNotificationContentModel) {
- updateHeader(content)
-
- updateTitle(title, content)
- updateText(bigText, content)
+ updateBase(content, textView = bigText)
}
private fun updateCall(content: PromotedNotificationContentModel) {
@@ -162,10 +181,7 @@ private class AODPromotedNotificationViewUpdater(root: View) {
}
private fun updateProgress(content: PromotedNotificationContentModel) {
- updateHeader(content)
-
- updateTitle(title, content)
- updateText(text, content)
+ updateBase(content)
updateNewProgressBar(content)
}
@@ -318,3 +334,5 @@ private class AODPromotedNotificationViewUpdater(root: View) {
}
private val viewUpdaterTagId = systemuiR.id.aod_promoted_notification_view_updater_tag
+
+private const val TAG = "AODPromotedNotification"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
index 395746280f6a..2af2068d49c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
@@ -30,6 +30,14 @@ interface AutomaticPromotionCoordinator : Coordinator {
* (but not normally promoted notifications).
*/
const val EXTRA_WAS_AUTOMATICALLY_PROMOTED = "android.wasAutomaticallyPromoted"
+
+ /**
+ * An extra set only on automatically promoted notifications that contains text that could
+ * reasonably be the short critical text. For now, we're only extracting arrival times. Will
+ * be set as a String.
+ */
+ const val EXTRA_AUTOMATICALLY_EXTRACTED_SHORT_CRITICAL_TEXT =
+ "android.automaticallyExtractedShortCriticalText"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
index df2eb08e8fa4..24d071c83a5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
@@ -26,9 +26,11 @@ import android.app.Notification.EXTRA_TEXT
import android.app.Notification.EXTRA_TITLE
import android.app.Notification.ProgressStyle
import android.content.Context
+import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_AUTOMATICALLY_EXTRACTED_SHORT_CRITICAL_TEXT
import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Companion.isPromotedForStatusBarChip
@@ -96,8 +98,7 @@ constructor(
primaryTextColor = colorsFromNotif.primaryTextColor,
)
- recoveredBuilder.style?.extractContent(contentBuilder)
- ?: run { contentBuilder.style = Style.Ineligible }
+ recoveredBuilder.extractStyleContent(contentBuilder)
return contentBuilder.build().also { logger.logExtractionSucceeded(entry, it) }
}
@@ -113,7 +114,13 @@ private fun Notification.shortCriticalText(): String? {
if (!android.app.Flags.apiRichOngoing()) {
return null
}
- return this.shortCriticalText
+ if (this.shortCriticalText != null) {
+ return this.shortCriticalText
+ }
+ if (Flags.promoteNotificationsAutomatically()) {
+ return this.extras?.getString(EXTRA_AUTOMATICALLY_EXTRACTED_SHORT_CRITICAL_TEXT)
+ }
+ return null
}
private fun Notification.chronometerCountDown(): Boolean =
@@ -132,28 +139,32 @@ private fun Notification.extractWhen(): When? {
}
}
-private fun Notification.Style.extractContent(
+private fun Notification.Builder.extractStyleContent(
contentBuilder: PromotedNotificationContentModel.Builder
) {
+ val style = this.style
+
contentBuilder.style =
- when (this) {
+ when (style) {
+ null -> Style.Base
+
is BigPictureStyle -> {
- extractContent(contentBuilder)
+ style.extractContent(contentBuilder)
Style.BigPicture
}
is BigTextStyle -> {
- extractContent(contentBuilder)
+ style.extractContent(contentBuilder)
Style.BigText
}
is CallStyle -> {
- extractContent(contentBuilder)
+ style.extractContent(contentBuilder)
Style.Call
}
is ProgressStyle -> {
- extractContent(contentBuilder)
+ style.extractContent(contentBuilder)
Style.Progress
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
index a175f90c384a..3dacae2114b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
@@ -131,6 +131,7 @@ data class PromotedNotificationContentModel(
/** The promotion-eligible style of a notification, or [Style.Ineligible] if not. */
enum class Style {
+ Base, // style == null
BigPicture,
BigText,
Call,
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 d986aaebc0f8..a6dde103e6ff 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
@@ -20,8 +20,8 @@ import static android.app.Flags.notificationsRedesignTemplates;
import static android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
-import static com.android.systemui.flags.Flags.ENABLE_NOTIFICATIONS_SIMULATE_SLOW_MEASURE;
import static com.android.systemui.Flags.notificationsPinnedHunInShade;
+import static com.android.systemui.flags.Flags.ENABLE_NOTIFICATIONS_SIMULATE_SLOW_MEASURE;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
import static com.android.systemui.statusbar.policy.RemoteInputView.FOCUS_ANIMATION_MIN_SCALE;
@@ -69,6 +69,9 @@ import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
+import androidx.dynamicanimation.animation.SpringAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
@@ -119,6 +122,7 @@ import com.android.systemui.statusbar.notification.shared.TransparentHeaderFix;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.statusbar.notification.stack.MagneticRowListener;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
@@ -131,6 +135,7 @@ import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
import com.android.systemui.util.Compile;
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.util.ListenerSet;
+import com.android.wm.shell.shared.animation.PhysicsAnimator;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -356,6 +361,45 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
};
+ private final SpringAnimation mMagneticAnimator = new SpringAnimation(
+ this, FloatPropertyCompat.createFloatPropertyCompat(TRANSLATE_CONTENT));
+
+ private final MagneticRowListener mMagneticRowListener = new MagneticRowListener() {
+
+ @Override
+ public void setMagneticTranslation(float translation) {
+ if (mMagneticAnimator.isRunning()) {
+ mMagneticAnimator.animateToFinalPosition(translation);
+ } else {
+ setTranslation(translation);
+ }
+ }
+
+ @Override
+ public void triggerMagneticForce(float endTranslation, @NonNull SpringForce springForce,
+ float startVelocity) {
+ cancelMagneticAnimations();
+ mMagneticAnimator.setSpring(springForce);
+ mMagneticAnimator.setStartVelocity(startVelocity);
+ mMagneticAnimator.animateToFinalPosition(endTranslation);
+ }
+
+ @Override
+ public void cancelMagneticAnimations() {
+ cancelSnapBackAnimation();
+ cancelTranslateAnimation();
+ mMagneticAnimator.cancel();
+ }
+ };
+
+ private void cancelSnapBackAnimation() {
+ PhysicsAnimator<ExpandableNotificationRow> animator =
+ PhysicsAnimator.getInstanceIfExists(this /* target */);
+ if (animator != null) {
+ animator.cancel();
+ }
+ }
+
/**
* Toggles expansion state.
*/
@@ -1203,15 +1247,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
/**
- * Prepares expansion changed.
- */
- public void prepareExpansionChanged() {
- if (mIsSummaryWithChildren) {
- mChildrenContainer.prepareExpansionChanged();
- }
- }
-
- /**
* Starts child animations.
*/
public void startChildAnimation(AnimationProperties properties) {
@@ -1525,7 +1560,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
// Let's update our childrencontainer. This is intentionally not guarded with
// mIsSummaryWithChildren since we might have had children but not anymore.
if (mChildrenContainer != null) {
- mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.getSbn());
+ mChildrenContainer.reInflateViews(mExpandClickListener);
}
if (mGuts != null) {
NotificationGuts oldGuts = mGuts;
@@ -4285,4 +4320,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
mLogger.logRemoveTransientRow(row.getEntry(), getEntry());
}
+
+ public MagneticRowListener getMagneticRowListener() {
+ return mMagneticRowListener;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
index 1ff0d9262476..92c10abff735 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
@@ -288,14 +288,21 @@ public class HybridConversationNotificationView extends HybridNotificationView {
public void setText(
CharSequence titleText,
CharSequence contentText,
- CharSequence conversationSenderName
+ CharSequence conversationSenderName,
+ @Nullable String summarization
) {
if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return;
- if (conversationSenderName == null) {
+ if (summarization != null) {
mConversationSenderName.setVisibility(GONE);
+ titleText = null;
+ contentText = summarization;
} else {
- mConversationSenderName.setVisibility(VISIBLE);
- mConversationSenderName.setText(conversationSenderName);
+ if (conversationSenderName == null) {
+ mConversationSenderName.setVisibility(GONE);
+ } else {
+ mConversationSenderName.setVisibility(VISIBLE);
+ mConversationSenderName.setText(conversationSenderName);
+ }
}
// TODO (b/217799515): super.bind() doesn't use contentView, remove the contentView
// argument when the flag is removed
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 c0dbb37c1b36..13ed6c449797 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
@@ -217,7 +217,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
messagingStyle,
builder,
row.getContext(),
- false
+ false,
+ entry.getRanking().getSummarization()
);
// If the messagingStyle is null, we want to inflate the normal view
isConversation = viewModel.isConversation();
@@ -239,7 +240,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
messagingStyle,
builder,
row.getContext(),
- true);
+ true,
+ entry.getRanking().getSummarization());
} else {
result.mPublicInflatedSingleLineViewModel =
SingleLineViewInflater.inflateRedactedSingleLineViewModel(
@@ -1318,7 +1320,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
messagingStyle,
recoveredBuilder,
mContext,
- false
+ false,
+ mEntry.getRanking().getSummarization()
);
result.mInflatedSingleLineView =
SingleLineViewInflater.inflatePrivateSingleLineView(
@@ -1338,7 +1341,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
messagingStyle,
recoveredBuilder,
mContext,
- true
+ true,
+ null
);
} else {
result.mPublicInflatedSingleLineViewModel =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index bf738aa1128f..d213c78a82c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -264,6 +264,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
NotificationEntry entry = mParent.getEntry();
int personNotifType = mPeopleNotificationIdentifier.getPeopleNotificationType(entry);
if (android.app.Flags.notificationClassificationUi()
+ && entry.getChannel() != null
&& SYSTEM_RESERVED_IDS.contains(entry.getChannel().getId())) {
// Bundled notification; create bundle-specific guts.
mInfoItem = createBundleItem(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
index 0b299d965b09..f4aae6e288a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
@@ -719,6 +719,7 @@ constructor(
builder = builder,
systemUiContext = systemUiContext,
redactText = false,
+ summarization = entry.ranking.summarization
)
} else null
@@ -735,6 +736,7 @@ constructor(
builder = builder,
systemUiContext = systemUiContext,
redactText = true,
+ summarization = null
)
} else {
SingleLineViewInflater.inflateRedactedSingleLineViewModel(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
index 6e78f561cfc1..a0b04155151c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
@@ -24,6 +24,7 @@ import com.android.systemui.log.dagger.NotificationLog
import com.android.systemui.log.dagger.NotificationRenderLog
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
+import com.android.systemui.statusbar.notification.stack.MagneticNotificationRowManagerImpl
import javax.inject.Inject
class NotificationRowLogger
@@ -203,6 +204,21 @@ constructor(
{ "onAppearAnimationFinished childKey: $str1 isAppear:$bool1 cancelled:$bool2" },
)
}
+
+ fun logMagneticAndRoundableTargetsNotSet(
+ state: MagneticNotificationRowManagerImpl.State,
+ entry: NotificationEntry,
+ ) {
+ buffer.log(
+ TAG,
+ LogLevel.ERROR,
+ {
+ str1 = entry.logKey
+ str2 = state.name
+ },
+ { "Failed to set magnetic and roundable targets for $str1 on state $str2." },
+ )
+ }
}
private const val TAG = "NotifRow"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
index fe2803bfc5d6..c051513ef3b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
@@ -61,6 +61,7 @@ internal object SingleLineViewInflater {
builder: Notification.Builder,
systemUiContext: Context,
redactText: Boolean,
+ summarization: String?
): SingleLineViewModel {
if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) {
return SingleLineViewModel(null, null, null)
@@ -108,6 +109,7 @@ internal object SingleLineViewInflater {
conversationSenderName =
if (isGroupConversation) conversationTextData?.senderName else null,
avatar = conversationAvatar,
+ summarization = summarization
)
return SingleLineViewModel(
@@ -132,6 +134,7 @@ internal object SingleLineViewInflater {
.ic_redacted_notification_single_line_icon
)
),
+ null
)
} else {
null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
index a17197c1f8ea..a50fc4c7986a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
@@ -32,6 +32,7 @@ object SingleLineViewBinder {
viewModel?.titleText,
viewModel?.contentText,
viewModel?.conversationData?.conversationSenderName,
+ viewModel?.conversationData?.summarization
)
} else {
// bind the title and content text views
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/SingleLineViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/SingleLineViewModel.kt
index d583fa5d97ed..32ded25f18a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/SingleLineViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/SingleLineViewModel.kt
@@ -46,6 +46,7 @@ data class SingleLineViewModel(
data class ConversationData(
val conversationSenderName: CharSequence?,
val avatar: ConversationAvatar,
+ val summarization: String?
)
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationBundleUi.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationBundleUi.kt
new file mode 100644
index 000000000000..72372319009c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationBundleUi.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.shared
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for reading or using the notification bundle ui flag state. */
+@Suppress("NOTHING_TO_INLINE")
+object NotificationBundleUi {
+ /** The aconfig flag name */
+ const val FLAG_NAME = Flags.FLAG_NOTIFICATION_BUNDLE_UI
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ /** Is the refactor enabled */
+ @JvmStatic
+ inline val isEnabled
+ get() = Flags.notificationBundleUi()
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This protects users from the
+ * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+ * build to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This will throw an exception if
+ * the flag is not enabled to ensure that the refactor author catches issues in testing.
+ * Caution!! Using this check incorrectly will cause crashes in nextfood builds!
+ */
+ @JvmStatic
+ inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManager.kt
new file mode 100644
index 000000000000..02336e42c26a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManager.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.stack
+
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+
+/**
+ * An interface to coordinate the magnetic behavior of notifications when swiped.
+ *
+ * During swiping a notification, this manager receives calls to set the horizontal translation of
+ * the notification and events that indicate that the interaction with the notification ended ( see
+ * the documentation for [onMagneticInteractionEnd]). The latter represent events when the
+ * notification is swiped out by dragging or flinging, or when it snaps back when the view is
+ * released from the gesture.
+ *
+ * This manager uses all of these inputs to implement a magnetic attachment between the notification
+ * swiped and its neighbors, as well as a detaching moment after crossing a threshold.
+ */
+interface MagneticNotificationRowManager {
+
+ /**
+ * Set the swipe threshold in pixels. After crossing the threshold, the magnetic target detaches
+ * and the magnetic neighbors snap back.
+ *
+ * @param[threshold] Swipe threshold in pixels.
+ */
+ fun setSwipeThresholdPx(thresholdPx: Float)
+
+ /**
+ * Set the magnetic and roundable targets of a magnetic swipe interaction.
+ *
+ * This method should construct and set a list of [MagneticRowListener] objects and a
+ * [RoundableTargets] object when an [ExpandableNotificationRow] starts to be swiped. The
+ * magnetic targets interact magnetically as the [expandableNotificationRow] is swiped, and the
+ * [RoundableTargets] get rounded when the row detaches from its magnetic couplings.
+ *
+ * This method must be called when the [swipingRow] starts to be swiped. It represents the
+ * beginning of the magnetic swipe.
+ *
+ * @param[swipingRow] The [ExpandableNotificationRow] that is being swiped. This is the main
+ * magnetic element that pulls its neighbors as it is swiped.
+ * @param[stackScrollLayout] The [NotificationStackScrollLayout] that contains notifications.
+ * @param[sectionsManager] The [NotificationSectionsManager] that helps identify roundable
+ * targets.
+ */
+ fun setMagneticAndRoundableTargets(
+ swipingRow: ExpandableNotificationRow,
+ stackScrollLayout: NotificationStackScrollLayout,
+ sectionsManager: NotificationSectionsManager,
+ )
+
+ /**
+ * Set the translation of an [ExpandableNotificationRow].
+ *
+ * This method must be called after [setMagneticAndRoundableTargets] has been called and must be
+ * called for each movement on the [row] being that is being swiped.
+ *
+ * @return true if the given [row] is the current magnetic view being swiped by the user, false
+ * otherwise. If false, no translation is applied and this method has no effect.
+ */
+ fun setMagneticRowTranslation(row: ExpandableNotificationRow, translation: Float): Boolean
+
+ /**
+ * Notifies that the magnetic interactions with the [ExpandableNotificationRow] stopped.
+ *
+ * This occurs if the row stopped being swiped and will snap back, or if it was ultimately
+ * dismissed. This method represents the end of the magnetic interaction and must be called
+ * after calls to [setMagneticRowTranslation].
+ *
+ * @param[row] [ExpandableNotificationRow] that stopped whose interaction stopped.
+ * @param[velocity] Optional velocity at the end of the interaction. Use this to trigger
+ * animations with a start velocity.
+ */
+ fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float? = null)
+
+ /**
+ * Reset any magnetic and roundable targets set, as well as any internal state.
+ *
+ * This method is in charge of proper cleanup by cancelling animations, clearing targets and
+ * resetting any internal state in the implementation. One use case of this method is when
+ * notifications must be cleared in the middle of a magnetic interaction and
+ * [onMagneticInteractionEnd] will not be called from the lifecycle of the user gesture.
+ */
+ fun reset()
+
+ companion object {
+ /** Detaching threshold in dp */
+ const val MAGNETIC_DETACH_THRESHOLD_DP = 56
+
+ /* An empty implementation of a manager */
+ @JvmStatic
+ val Empty: MagneticNotificationRowManager
+ get() =
+ object : MagneticNotificationRowManager {
+ override fun setSwipeThresholdPx(thresholdPx: Float) {}
+
+ override fun setMagneticAndRoundableTargets(
+ swipingRow: ExpandableNotificationRow,
+ stackScrollLayout: NotificationStackScrollLayout,
+ sectionsManager: NotificationSectionsManager,
+ ) {}
+
+ override fun setMagneticRowTranslation(
+ row: ExpandableNotificationRow,
+ translation: Float,
+ ): Boolean = false
+
+ override fun onMagneticInteractionEnd(
+ row: ExpandableNotificationRow,
+ velocity: Float?,
+ ) {}
+
+ override fun reset() {}
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
new file mode 100644
index 000000000000..bddff12be280
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.stack
+
+import android.os.VibrationAttributes
+import androidx.dynamicanimation.animation.SpringForce
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.NotificationRowLogger
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.InteractionProperties
+import com.google.android.msdl.domain.MSDLPlayer
+import javax.inject.Inject
+import kotlin.math.abs
+import kotlin.math.pow
+
+@SysUISingleton
+class MagneticNotificationRowManagerImpl
+@Inject
+constructor(
+ private val msdlPlayer: MSDLPlayer,
+ private val notificationTargetsHelper: NotificationTargetsHelper,
+ private val notificationRoundnessManager: NotificationRoundnessManager,
+ private val logger: NotificationRowLogger,
+) : MagneticNotificationRowManager {
+
+ var currentState = State.IDLE
+ private set
+
+ // Magnetic and roundable targets
+ var currentMagneticListeners = listOf<MagneticRowListener?>()
+ private set
+
+ var currentRoundableTargets: RoundableTargets? = null
+ private set
+
+ private var magneticDetachThreshold = Float.POSITIVE_INFINITY
+
+ // Animation spring forces
+ private val detachForce =
+ SpringForce().setStiffness(DETACH_STIFFNESS).setDampingRatio(DETACH_DAMPING_RATIO)
+ private val snapForce =
+ SpringForce().setStiffness(SNAP_BACK_STIFFNESS).setDampingRatio(SNAP_BACK_DAMPING_RATIO)
+
+ // Multiplier applied to the translation of a row while swiped
+ private val swipedRowMultiplier =
+ MAGNETIC_TRANSLATION_MULTIPLIERS[MAGNETIC_TRANSLATION_MULTIPLIERS.size / 2]
+
+ override fun setSwipeThresholdPx(thresholdPx: Float) {
+ magneticDetachThreshold = thresholdPx
+ }
+
+ override fun setMagneticAndRoundableTargets(
+ swipingRow: ExpandableNotificationRow,
+ stackScrollLayout: NotificationStackScrollLayout,
+ sectionsManager: NotificationSectionsManager,
+ ) {
+ if (currentState == State.IDLE) {
+ updateMagneticAndRoundableTargets(swipingRow, stackScrollLayout, sectionsManager)
+ currentState = State.TARGETS_SET
+ } else {
+ logger.logMagneticAndRoundableTargetsNotSet(currentState, swipingRow.entry)
+ }
+ }
+
+ private fun updateMagneticAndRoundableTargets(
+ expandableNotificationRow: ExpandableNotificationRow,
+ stackScrollLayout: NotificationStackScrollLayout,
+ sectionsManager: NotificationSectionsManager,
+ ) {
+ // Update roundable targets
+ currentRoundableTargets =
+ notificationTargetsHelper.findRoundableTargets(
+ expandableNotificationRow,
+ stackScrollLayout,
+ sectionsManager,
+ )
+
+ // Update magnetic targets
+ val newListeners =
+ notificationTargetsHelper.findMagneticTargets(
+ expandableNotificationRow,
+ stackScrollLayout,
+ MAGNETIC_TRANSLATION_MULTIPLIERS.size,
+ )
+ newListeners.forEach {
+ if (currentMagneticListeners.contains(it)) {
+ it?.cancelMagneticAnimations()
+ }
+ }
+ currentMagneticListeners = newListeners
+ }
+
+ override fun setMagneticRowTranslation(
+ row: ExpandableNotificationRow,
+ translation: Float,
+ ): Boolean {
+ if (!row.isSwipedTarget()) return false
+
+ when (currentState) {
+ State.TARGETS_SET -> {
+ pullTargets(translation)
+ currentState = State.PULLING
+ }
+ State.PULLING -> {
+ val targetTranslation = swipedRowMultiplier * translation
+ val crossedThreshold = abs(targetTranslation) >= magneticDetachThreshold
+ if (crossedThreshold) {
+ snapNeighborsBack()
+ currentMagneticListeners.swipedListener()?.let { detach(it, translation) }
+ currentState = State.DETACHED
+ } else {
+ pullTargets(translation)
+ }
+ }
+ State.DETACHED -> {
+ val swiped = currentMagneticListeners.swipedListener()
+ swiped?.setMagneticTranslation(translation)
+ }
+ else -> {}
+ }
+ return true
+ }
+
+ private fun pullTargets(translation: Float) {
+ var targetTranslation: Float
+ currentMagneticListeners.forEachIndexed { i, listener ->
+ targetTranslation = MAGNETIC_TRANSLATION_MULTIPLIERS[i] * translation
+ listener?.setMagneticTranslation(targetTranslation)
+ }
+ playPullHaptics(mappedTranslation = swipedRowMultiplier * translation)
+ }
+
+ private fun playPullHaptics(mappedTranslation: Float) {
+ val normalizedTranslation = abs(mappedTranslation) / magneticDetachThreshold
+ val vibrationScale =
+ (normalizedTranslation * MAX_VIBRATION_SCALE).pow(VIBRATION_PERCEPTION_EXPONENT)
+ msdlPlayer.playToken(
+ MSDLToken.DRAG_INDICATOR_CONTINUOUS,
+ InteractionProperties.DynamicVibrationScale(
+ scale = vibrationScale,
+ vibrationAttributes = VIBRATION_ATTRIBUTES_PIPELINING,
+ ),
+ )
+ }
+
+ private fun snapNeighborsBack(velocity: Float? = null) {
+ currentMagneticListeners.forEachIndexed { i, target ->
+ target?.let {
+ if (i != currentMagneticListeners.size / 2) {
+ snapBack(it, velocity)
+ }
+ }
+ }
+ }
+
+ private fun detach(listener: MagneticRowListener, toPosition: Float) {
+ listener.cancelMagneticAnimations()
+ listener.triggerMagneticForce(toPosition, detachForce)
+ currentRoundableTargets?.let {
+ notificationRoundnessManager.setViewsAffectedBySwipe(it.before, it.swiped, it.after)
+ }
+ msdlPlayer.playToken(MSDLToken.SWIPE_THRESHOLD_INDICATOR)
+ }
+
+ private fun snapBack(listener: MagneticRowListener, velocity: Float?) {
+ listener.cancelMagneticAnimations()
+ listener.triggerMagneticForce(
+ endTranslation = 0f,
+ snapForce,
+ startVelocity = velocity ?: 0f,
+ )
+ }
+
+ override fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float?) {
+ if (!row.isSwipedTarget()) return
+
+ when (currentState) {
+ State.PULLING -> {
+ snapNeighborsBack(velocity)
+ currentState = State.IDLE
+ }
+ State.DETACHED -> {
+ currentState = State.IDLE
+ }
+ else -> {}
+ }
+ }
+
+ override fun reset() {
+ currentMagneticListeners.forEach { it?.cancelMagneticAnimations() }
+ currentState = State.IDLE
+ currentMagneticListeners = listOf()
+ currentRoundableTargets = null
+ }
+
+ private fun List<MagneticRowListener?>.swipedListener(): MagneticRowListener? =
+ getOrNull(index = size / 2)
+
+ private fun ExpandableNotificationRow.isSwipedTarget(): Boolean =
+ magneticRowListener == currentMagneticListeners.swipedListener()
+
+ enum class State {
+ IDLE,
+ TARGETS_SET,
+ PULLING,
+ DETACHED,
+ }
+
+ companion object {
+ /**
+ * Multipliers applied to the translation of magnetically-coupled views. This list must be
+ * symmetric with an odd size, where the center multiplier applies to the view that is
+ * currently being swiped. From the center outwards, the multipliers apply to the neighbors
+ * of the swiped view.
+ */
+ private val MAGNETIC_TRANSLATION_MULTIPLIERS = listOf(0.18f, 0.28f, 0.5f, 0.28f, 0.18f)
+
+ /** Spring parameters for physics animators */
+ private const val DETACH_STIFFNESS = 800f
+ private const val DETACH_DAMPING_RATIO = 0.95f
+ private const val SNAP_BACK_STIFFNESS = 550f
+ private const val SNAP_BACK_DAMPING_RATIO = 0.52f
+
+ private val VIBRATION_ATTRIBUTES_PIPELINING =
+ VibrationAttributes.Builder()
+ .setUsage(VibrationAttributes.USAGE_TOUCH)
+ .setFlags(VibrationAttributes.FLAG_PIPELINED_EFFECT)
+ .build()
+ private const val MAX_VIBRATION_SCALE = 0.2f
+ private const val VIBRATION_PERCEPTION_EXPONENT = 1 / 0.89f
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticRowListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticRowListener.kt
new file mode 100644
index 000000000000..8a1adfe95392
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticRowListener.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.stack
+
+import androidx.dynamicanimation.animation.SpringForce
+
+/** A listener that responds to magnetic forces applied to an [ExpandableNotificationRow] */
+interface MagneticRowListener {
+
+ /** Set a translation due to a magnetic attachment. */
+ fun setMagneticTranslation(translation: Float)
+
+ /**
+ * Trigger the magnetic behavior when the row detaches or snaps back from its magnetic
+ * couplings.
+ *
+ * @param[endTranslation] Translation that the row detaches to.
+ * @param[springForce] A [SpringForce] that guides the dynamics of the behavior towards the end
+ * translation. This could be a detachment spring force or a snap-back spring force.
+ * @param[startVelocity] A start velocity for the animation.
+ */
+ fun triggerMagneticForce(
+ endTranslation: Float,
+ springForce: SpringForce,
+ startVelocity: Float = 0f,
+ )
+
+ /** Cancel any animations related to the magnetic interactions of the row */
+ fun cancelMagneticAnimations()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 8e48065d9d1d..ea397b61fe84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -77,7 +77,7 @@ public class NotificationChildrenContainer extends ViewGroup
static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
public static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
private static final AnimationProperties ALPHA_FADE_IN = new AnimationProperties() {
- private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
+ private final AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
@Override
public AnimationFilter getAnimationFilter() {
@@ -123,6 +123,8 @@ public class NotificationChildrenContainer extends ViewGroup
private NotificationHeaderViewWrapper mMinimizedGroupHeaderWrapper;
private NotificationGroupingUtil mGroupingUtil;
private ViewState mHeaderViewState;
+ private ViewState mTopLineViewState;
+ private ViewState mExpandButtonViewState;
private int mClipBottomAmount;
private boolean mIsMinimized;
private OnClickListener mHeaderClickListener;
@@ -138,7 +140,7 @@ public class NotificationChildrenContainer extends ViewGroup
private float mHeaderVisibleAmount = 1.0f;
private int mUntruncatedChildCount;
private boolean mContainingNotificationIsFaded = false;
- private RoundableState mRoundableState;
+ private final RoundableState mRoundableState;
private int mMinSingleLineHeight;
private NotificationChildrenContainerLogger mLogger;
@@ -446,7 +448,7 @@ public class NotificationChildrenContainer extends ViewGroup
}
mGroupHeaderWrapper.setExpanded(mChildrenExpanded);
mGroupHeaderWrapper.onContentUpdated(mContainingNotification);
- recreateLowPriorityHeader(builder, isConversation);
+ recreateLowPriorityHeader(builder);
updateHeaderVisibility(false /* animate */);
updateChildrenAppearance();
Trace.endSection();
@@ -559,7 +561,7 @@ public class NotificationChildrenContainer extends ViewGroup
* @param builder a builder to reuse. Otherwise the builder will be recovered.
*/
@VisibleForTesting
- void recreateLowPriorityHeader(Notification.Builder builder, boolean isConversation) {
+ void recreateLowPriorityHeader(Notification.Builder builder) {
AsyncGroupHeaderViewInflation.assertInLegacyMode();
RemoteViews header;
StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
@@ -866,10 +868,7 @@ public class NotificationChildrenContainer extends ViewGroup
}
}
if (mGroupHeader != null) {
- if (mHeaderViewState == null) {
- mHeaderViewState = new ViewState();
- }
- mHeaderViewState.initFrom(mGroupHeader);
+ mHeaderViewState = initStateForGroupHeader(mHeaderViewState);
if (mContainingNotification.hasExpandingChild()) {
// Not modifying translationZ during expand animation.
@@ -881,38 +880,33 @@ public class NotificationChildrenContainer extends ViewGroup
}
mHeaderViewState.setYTranslation(mCurrentHeaderTranslation);
mHeaderViewState.setAlpha(mHeaderVisibleAmount);
- // The hiding is done automatically by the alpha, otherwise we'll pick it up again
- // in the next frame with the initFrom call above and have an invisible header
- mHeaderViewState.hidden = false;
+
+ if (notificationsRedesignTemplates()) {
+ mTopLineViewState = initStateForGroupHeader(mTopLineViewState);
+ mTopLineViewState.setYTranslation(
+ mGroupHeader.getTopLineTranslation() * expandFactor);
+
+ mExpandButtonViewState = initStateForGroupHeader(mExpandButtonViewState);
+ mExpandButtonViewState.setYTranslation(
+ mGroupHeader.getExpandButtonTranslation() * expandFactor);
+ }
}
}
/**
- * When moving into the bottom stack, the bottom visible child in an expanded group adjusts its
- * height, children in the group after this are gone.
- *
- * @param child the child who's height to adjust.
- * @param parentHeight the height of the parent.
- * @param childState the state to update.
- * @param yPosition the yPosition of the view.
- * @return true if children after this one should be hidden.
+ * Initialise a new ViewState for the group header or its children, or update and return
+ * {@code existingState} if not null.
*/
- private boolean updateChildStateForExpandedGroup(
- ExpandableNotificationRow child,
- int parentHeight,
- ExpandableViewState childState,
- int yPosition) {
- final int top = yPosition + child.getClipTopAmount();
- final int intrinsicHeight = child.getIntrinsicHeight();
- final int bottom = top + intrinsicHeight;
- int newHeight = intrinsicHeight;
- if (bottom >= parentHeight) {
- // Child is either clipped or gone
- newHeight = Math.max((parentHeight - top), 0);
- }
- childState.hidden = newHeight == 0;
- childState.height = newHeight;
- return childState.height != intrinsicHeight && !childState.hidden;
+ private ViewState initStateForGroupHeader(ViewState existingState) {
+ ViewState viewState = existingState;
+ if (viewState == null) {
+ viewState = new ViewState();
+ }
+ viewState.initFrom(mGroupHeader);
+ // The hiding is done automatically by the alpha, otherwise we'll pick it up again
+ // in the next frame with the initFrom call above and have an invisible header
+ viewState.hidden = false;
+ return viewState;
}
@VisibleForTesting
@@ -976,6 +970,14 @@ public class NotificationChildrenContainer extends ViewGroup
if (mHeaderViewState != null) {
mHeaderViewState.applyToView(mGroupHeader);
}
+ if (notificationsRedesignTemplates()) {
+ if (mTopLineViewState != null) {
+ mTopLineViewState.applyToView(mGroupHeader.getTopLineView());
+ }
+ if (mExpandButtonViewState != null) {
+ mExpandButtonViewState.applyToView(mGroupHeader.getExpandButton());
+ }
+ }
updateChildrenClipping();
}
@@ -1010,7 +1012,7 @@ public class NotificationChildrenContainer extends ViewGroup
}
@Override
- protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+ protected boolean drawChild(@NonNull Canvas canvas, View child, long drawingTime) {
boolean isCanvasChanged = false;
Path clipPath = mChildClipPath;
@@ -1062,16 +1064,6 @@ public class NotificationChildrenContainer extends ViewGroup
}
}
-
- /**
- * This is called when the children expansion has changed and positions the children properly
- * for an appear animation.
- */
- public void prepareExpansionChanged() {
- // TODO: do something that makes sense, like placing the invisible views correctly
- return;
- }
-
/**
* Animate to a given state.
*/
@@ -1478,7 +1470,7 @@ public class NotificationChildrenContainer extends ViewGroup
return mIsMinimized && !mContainingNotification.isExpanded();
}
- public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
+ public void reInflateViews(OnClickListener listener) {
if (!AsyncGroupHeaderViewInflation.isEnabled()) {
// When Async header inflation is enabled, we do not reinflate headers because they are
// inflated from the background thread
@@ -1567,7 +1559,7 @@ public class NotificationChildrenContainer extends ViewGroup
mIsMinimized = isMinimized;
if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
if (!AsyncGroupHeaderViewInflation.isEnabled()) {
- recreateLowPriorityHeader(null /* existingBuilder */, mIsConversation);
+ recreateLowPriorityHeader(null /* existingBuilder */);
}
updateHeaderVisibility(false /* animate */);
}
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 bf24c873c693..876090101f6e 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
@@ -24,6 +24,7 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.app.tracing.TrackGroupUtils.trackGroup;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_CLEAR_ALL;
+import static com.android.systemui.Flags.magneticNotificationSwipes;
import static com.android.systemui.Flags.notificationOverExpansionClippingFix;
import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
@@ -5787,17 +5788,21 @@ public class NotificationStackScrollLayout
getChildrenWithBackground()
);
- RoundableTargets targets = mController.getNotificationTargetsHelper().findRoundableTargets(
- (ExpandableNotificationRow) viewSwiped,
- this,
- mSectionsManager
- );
+ if (!magneticNotificationSwipes()) {
+ RoundableTargets targets = mController
+ .getNotificationTargetsHelper()
+ .findRoundableTargets(
+ (ExpandableNotificationRow) viewSwiped,
+ this,
+ mSectionsManager);
- mController.getNotificationRoundnessManager()
- .setViewsAffectedBySwipe(
- targets.getBefore(),
- targets.getSwiped(),
- targets.getAfter());
+ mController.getNotificationRoundnessManager()
+ .setViewsAffectedBySwipe(
+ targets.getBefore(),
+ targets.getSwiped(),
+ targets.getAfter());
+
+ }
updateFirstAndLastBackgroundViews();
requestDisallowInterceptTouchEvent(true);
@@ -6678,10 +6683,23 @@ public class NotificationStackScrollLayout
}
NotificationHeaderView header = childrenContainer.getGroupHeader();
if (header != null) {
+ resetYTranslation(header.getTopLineView());
+ resetYTranslation(header.getExpandButton());
header.centerTopLine(expanded);
}
}
+ /**
+ * Reset the y translation of the {@code view} via the {@link ViewState}, to ensure that the
+ * animation state is updated correctly.
+ */
+ private static void resetYTranslation(View view) {
+ ViewState viewState = new ViewState();
+ viewState.initFrom(view);
+ viewState.setYTranslation(0);
+ viewState.applyToView(view);
+ }
+
private final ExpandHelper.Callback mExpandHelperCallback = new ExpandHelper.Callback() {
@Override
public ExpandableView getChildAtPosition(float touchX, float touchY) {
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 8eaef3681e5c..804824569f1e 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
@@ -188,6 +188,8 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
private final StackStateLogger mStackStateLogger;
private final NotificationStackScrollLogger mLogger;
+ private final MagneticNotificationRowManager mMagneticNotificationRowManager;
+ private final NotificationSectionsManager mSectionsManager;
private final GroupExpansionManager mGroupExpansionManager;
private NotificationStackScrollLayout mView;
@@ -465,6 +467,28 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
@Override
+ public void onDensityScaleChange(float density) {
+ mMagneticNotificationRowManager.setSwipeThresholdPx(
+ density * MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP
+ );
+ }
+
+ @Override
+ public boolean handleSwipeableViewTranslation(SwipeableView view, float translate) {
+ if (view instanceof ExpandableNotificationRow row) {
+ return mMagneticNotificationRowManager
+ .setMagneticRowTranslation(row, translate);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void resetMagneticStates() {
+ mMagneticNotificationRowManager.reset();
+ }
+
+ @Override
public void onSnooze(StatusBarNotification sbn,
NotificationSwipeActionHelper.SnoozeOption snoozeOption) {
mNotificationsController.setNotificationSnoozed(sbn, snoozeOption);
@@ -479,6 +503,14 @@ public class NotificationStackScrollLayoutController implements Dumpable {
public void onDragCancelled(View v) {
}
+ @Override
+ public void onDragCancelledWithVelocity(View v, float finalVelocity) {
+ if (v instanceof ExpandableNotificationRow row) {
+ mMagneticNotificationRowManager.onMagneticInteractionEnd(
+ row, finalVelocity);
+ }
+ }
+
/**
* Handles cleanup after the given {@code view} has been fully swiped out (including
* re-invoking dismiss logic in case the notification has not made its way out yet).
@@ -506,6 +538,10 @@ public class NotificationStackScrollLayoutController implements Dumpable {
*/
public void handleChildViewDismissed(View view) {
+ if (view instanceof ExpandableNotificationRow row) {
+ mMagneticNotificationRowManager.onMagneticInteractionEnd(
+ row, null /* velocity */);
+ }
// The View needs to clean up the Swipe states, e.g. roundness.
mView.onSwipeEnd();
if (mView.getClearAllInProgress()) {
@@ -577,6 +613,10 @@ public class NotificationStackScrollLayoutController implements Dumpable {
@Override
public void onBeginDrag(View v) {
+ if (v instanceof ExpandableNotificationRow row) {
+ mMagneticNotificationRowManager.setMagneticAndRoundableTargets(
+ row, mView, mSectionsManager);
+ }
mView.onSwipeBegin(v);
}
@@ -691,7 +731,9 @@ public class NotificationStackScrollLayoutController implements Dumpable {
ActivityStarter activityStarter,
SplitShadeStateController splitShadeStateController,
SensitiveNotificationProtectionController sensitiveNotificationProtectionController,
- WallpaperInteractor wallpaperInteractor) {
+ WallpaperInteractor wallpaperInteractor,
+ MagneticNotificationRowManager magneticNotificationRowManager,
+ NotificationSectionsManager sectionsManager) {
mView = view;
mViewBinder = viewBinder;
mStackStateLogger = stackLogger;
@@ -742,6 +784,8 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mSensitiveNotificationProtectionController = sensitiveNotificationProtectionController;
mWallpaperInteractor = wallpaperInteractor;
mView.passSplitShadeStateController(splitShadeStateController);
+ mMagneticNotificationRowManager = magneticNotificationRowManager;
+ mSectionsManager = sectionsManager;
if (SceneContainerFlag.isEnabled()) {
mWakeUpCoordinator.setStackScroller(this);
}
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 50457449f466..d476d482226d 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
@@ -34,7 +34,6 @@ import android.view.ViewConfiguration;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.systemui.SwipeHelper;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.FalsingManager;
@@ -363,7 +362,7 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
superSnapChild(animView, targetLeft, velocity);
}
- mCallback.onDragCancelled(animView);
+ mCallback.onDragCancelledWithVelocity(animView, velocity);
if (targetLeft == 0) {
handleMenuCoveredOrDismissed();
}
@@ -404,7 +403,11 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
@Override
public void setTranslation(View v, float translate) {
if (v instanceof SwipeableView) {
- ((SwipeableView) v).setTranslation(translate);
+ boolean setTranslationHandled =
+ mCallback.handleSwipeableViewTranslation((SwipeableView) v, translate);
+ if (!setTranslationHandled) {
+ ((SwipeableView) v).setTranslation(translate);
+ }
}
}
@@ -529,6 +532,18 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
mPulsing = pulsing;
}
+ @Override
+ public void setDensityScale(float densityScale) {
+ super.setDensityScale(densityScale);
+ mCallback.onDensityScaleChange(densityScale);
+ }
+
+ @Override
+ public void resetTouchState() {
+ super.resetTouchState();
+ mCallback.resetMagneticStates();
+ }
+
public interface NotificationCallback extends SwipeHelper.Callback{
/**
* @return if the view should be dismissed as soon as the touch is released, otherwise its
@@ -548,6 +563,13 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
* @param animView the view to ask about
*/
float getTotalTranslationLength(View animView);
+
+ void onDensityScaleChange(float density);
+
+ boolean handleSwipeableViewTranslation(SwipeableView view, float translate);
+
+ // Reset any ongoing magnetic interactions
+ void resetMagneticStates();
}
static class Builder {
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 02662f409a87..74e8b8ef29c2 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
@@ -3,7 +3,6 @@ package com.android.systemui.statusbar.notification.stack
import androidx.core.view.children
import androidx.core.view.isVisible
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.statusbar.notification.Roundable
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
@@ -14,11 +13,7 @@ import javax.inject.Inject
* ([Roundable]) above and below the current one (see [findRoundableTargets]).
*/
@SysUISingleton
-class NotificationTargetsHelper
-@Inject
-constructor(
- featureFlags: FeatureFlags,
-) {
+class NotificationTargetsHelper @Inject constructor() {
/**
* This method looks for views that can be rounded (and implement [Roundable]) during a
@@ -74,11 +69,80 @@ constructor(
}
}
- return RoundableTargets(
- before = viewBefore,
- swiped = viewSwiped,
- after = viewAfter,
- )
+ return RoundableTargets(before = viewBefore, swiped = viewSwiped, after = viewAfter)
+ }
+
+ /**
+ * This method looks for [ExpandableNotificationRow]s that can magnetically attach to a swiped
+ * [ExpandableNotificationRow] and returns their [MagneticRowListener]s in a list.
+ *
+ * The list contains the swiped row's listener at the center of the list. From the center
+ * towards the left, the list contains the closest notification neighbors above the swiped row.
+ * From the center towards the right, the list contains the closest neighbors below the row.
+ *
+ * The list is filled from the center outwards, stopping at the first neighbor that is not an
+ * [ExpandableNotificationRow]. In addition, the list does not cross the boundaries of a
+ * notification group. Positions where the list halted are filled with null.
+ *
+ * @param[viewSwiped] The [ExpandableNotificationRow] that is swiped.
+ * @param[stackScrollLayout] [NotificationStackScrollLayout] container.
+ * @param[totalMagneticTargets] The total number of magnetic listeners in the resulting list.
+ * This includes the listener of the view swiped.
+ * @return The list of [MagneticRowListener]s above and below the swiped
+ * [ExpandableNotificationRow]
+ */
+ fun findMagneticTargets(
+ viewSwiped: ExpandableNotificationRow,
+ stackScrollLayout: NotificationStackScrollLayout,
+ totalMagneticTargets: Int,
+ ): List<MagneticRowListener?> {
+ val notificationParent = viewSwiped.notificationParent
+ val childrenContainer = notificationParent?.childrenContainer
+ val visibleStackChildren =
+ stackScrollLayout.children
+ .filterIsInstance<ExpandableView>()
+ .filter { it.isVisible }
+ .toList()
+
+ val container: List<ExpandableView> =
+ if (notificationParent != null && childrenContainer != null) {
+ // We are inside a notification group
+ childrenContainer.attachedChildren.filter { it.isVisible }
+ } else {
+ visibleStackChildren
+ }
+
+ // Construct the list of targets
+ val magneticTargets = MutableList<MagneticRowListener?>(totalMagneticTargets) { null }
+ magneticTargets[totalMagneticTargets / 2] = viewSwiped.magneticRowListener
+
+ // Fill the list outwards from the center
+ val centerIndex = container.indexOf(viewSwiped)
+ var leftIndex = magneticTargets.size / 2 - 1
+ var rightIndex = magneticTargets.size / 2 + 1
+ var canMoveLeft = true
+ var canMoveRight = true
+ for (distance in 1..totalMagneticTargets / 2) {
+ if (canMoveLeft) {
+ val leftElement = container.getOrNull(index = centerIndex - distance)
+ if (leftElement is ExpandableNotificationRow) {
+ magneticTargets[leftIndex] = leftElement.magneticRowListener
+ leftIndex--
+ } else {
+ canMoveLeft = false
+ }
+ }
+ if (canMoveRight) {
+ val rightElement = container.getOrNull(index = centerIndex + distance)
+ if (rightElement is ExpandableNotificationRow) {
+ magneticTargets[rightIndex] = rightElement.magneticRowListener
+ rightIndex++
+ } else {
+ canMoveRight = false
+ }
+ }
+ }
+ return magneticTargets
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 4686bef9ca5a..c783250f2e0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -468,10 +468,6 @@ public class StackStateAnimator {
if (isFullySwipedOut) {
changingView.removeFromTransientContainer();
}
- } else if (event.animationType == NotificationStackScrollLayout
- .AnimationEvent.ANIMATION_TYPE_GROUP_EXPANSION_CHANGED) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) event.mChangingView;
- row.prepareExpansionChanged();
} else if (event.animationType == ANIMATION_TYPE_HEADS_UP_CYCLING_IN) {
mHeadsUpAppearChildren.add(changingView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractor.kt
index 53d0c2e879e3..1904bc5bbb8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/HideNotificationsInteractor.kt
@@ -30,7 +30,6 @@ import com.android.systemui.util.kotlin.area
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.race
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -41,7 +40,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.withTimeout
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class HideNotificationsInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
index b6ce70826f9e..107875df6bfa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
@@ -29,7 +29,6 @@ import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.policy.SplitShadeStateController
import dagger.Lazy
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -40,7 +39,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
/** Encapsulates business-logic specifically related to the shared notification stack container. */
-@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
+@OptIn(FlowPreview::class)
@SysUISingleton
class SharedNotificationContainerInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index c1d022600559..b6d89ecf29f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -15,8 +15,6 @@
*
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.statusbar.notification.stack.ui.viewmodel
import android.content.Context
@@ -92,7 +90,6 @@ import com.android.systemui.util.kotlin.sample
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
index 33e4fed4073c..7289c2ed5897 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
@@ -66,14 +66,12 @@ import com.android.systemui.util.kotlin.getOrNull
import dagger.Lazy
import java.util.Optional
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/**
* Encapsulates the activity logic for activity starter when the SceneContainerFlag is enabled.
*
* TODO: b/308819693
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
class ActivityStarterInternalImpl
@Inject
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 afc5bc67c0a1..04dedb629a15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -71,8 +71,6 @@ import com.android.systemui.util.time.SystemClock;
import dagger.Lazy;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -86,7 +84,6 @@ import javax.inject.Inject;
/**
* Controller which coordinates all the biometric unlocking actions with the UI.
*/
-@ExperimentalCoroutinesApi
@SysUISingleton
public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable {
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 6922de5739ab..09531c3b18bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -64,14 +64,12 @@ import dagger.Lazy;
import kotlin.Unit;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
import javax.inject.Inject;
/**
* Implementation of DozeHost for SystemUI.
*/
-@ExperimentalCoroutinesApi @SysUISingleton
+@SysUISingleton
public final class DozeServiceHost implements DozeHost {
private static final String TAG = "DozeServiceHost";
private final IListenerSet<Callback> mCallbacks = new CopyOnLoopListenerSet<>();
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 be48c3d928f4..d5f456fea2a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -84,7 +84,6 @@ import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -99,7 +98,6 @@ import javax.inject.Inject;
* security method gets shown).
*/
@SysUISingleton
-@ExperimentalCoroutinesApi
public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dumpable {
static final String TAG = "ScrimController";
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 8443edd6aa87..b2c4ef95242b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -111,7 +111,6 @@ import dagger.Lazy;
import kotlin.Unit;
import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
import kotlinx.coroutines.Job;
import java.io.PrintWriter;
@@ -130,7 +129,7 @@ import javax.inject.Inject;
* which is in turn, reported to this class by the current
* {@link com.android.keyguard.KeyguardViewController}.
*/
-@ExperimentalCoroutinesApi @SysUISingleton
+@SysUISingleton
public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
ShadeExpansionListener, NavigationModeController.ModeChangedListener,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
index 99141f592a2e..ba7628fb3c07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
@@ -32,7 +32,6 @@ import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCall
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -56,7 +55,6 @@ import kotlinx.coroutines.flow.stateIn
* visible
* * - [OngoingCallModel.InCall] when there is a call notification and the call app is not visible
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class OngoingCallInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
index 9f1395a30610..f82e681de76f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
@@ -81,12 +81,7 @@ constructor(
awaitClose { observer.isListening = false }
}
.distinctUntilChanged()
- .logDiffsForTable(
- logger,
- columnPrefix = "",
- columnName = "isAirplaneMode",
- initialValue = false,
- )
+ .logDiffsForTable(logger, columnName = "isAirplaneMode", initialValue = false)
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
index bd18f4bd1f56..2cef54f9cf5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
@@ -59,7 +59,6 @@ constructor(
.distinctUntilChanged()
.logDiffsForTable(
logger,
- columnPrefix = "",
columnName = "isAirplaneModeIconVisible",
initialValue = false,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
index 252ebe6a32b0..66587c779fbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
@@ -30,7 +30,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.Mobil
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -62,7 +61,6 @@ import kotlinx.coroutines.flow.stateIn
* implementation.
*/
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MobileRepositorySwitcher
@Inject
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
index be3977ecd4ba..410389a8d94c 100644
--- 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
@@ -64,9 +64,8 @@ class DemoMobileConnectionRepository(
_carrierId
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CARRIER_ID,
- _carrierId.value,
+ initialValue = _carrierId.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _carrierId.value)
@@ -75,9 +74,8 @@ class DemoMobileConnectionRepository(
_inflateSignalStrength
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "inflate",
- _inflateSignalStrength.value,
+ initialValue = _inflateSignalStrength.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _inflateSignalStrength.value)
@@ -89,9 +87,8 @@ class DemoMobileConnectionRepository(
_isEmergencyOnly
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_EMERGENCY,
- _isEmergencyOnly.value,
+ initialValue = _isEmergencyOnly.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value)
@@ -100,9 +97,8 @@ class DemoMobileConnectionRepository(
_isRoaming
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_ROAMING,
- _isRoaming.value,
+ initialValue = _isRoaming.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value)
@@ -111,9 +107,8 @@ class DemoMobileConnectionRepository(
_operatorAlphaShort
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_OPERATOR,
- _operatorAlphaShort.value,
+ initialValue = _operatorAlphaShort.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value)
@@ -122,9 +117,8 @@ class DemoMobileConnectionRepository(
_isInService
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_IN_SERVICE,
- _isInService.value,
+ initialValue = _isInService.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value)
@@ -133,21 +127,15 @@ class DemoMobileConnectionRepository(
_isNonTerrestrial
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_NTN,
- _isNonTerrestrial.value,
+ initialValue = _isNonTerrestrial.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isNonTerrestrial.value)
private val _isGsm = MutableStateFlow(false)
override val isGsm =
_isGsm
- .logDiffsForTable(
- tableLogBuffer,
- columnPrefix = "",
- columnName = COL_IS_GSM,
- _isGsm.value,
- )
+ .logDiffsForTable(tableLogBuffer, columnName = COL_IS_GSM, initialValue = _isGsm.value)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value)
private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
@@ -155,9 +143,8 @@ class DemoMobileConnectionRepository(
_cdmaLevel
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CDMA_LEVEL,
- _cdmaLevel.value,
+ initialValue = _cdmaLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value)
@@ -166,9 +153,8 @@ class DemoMobileConnectionRepository(
_primaryLevel
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_PRIMARY_LEVEL,
- _primaryLevel.value,
+ initialValue = _primaryLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value)
@@ -177,23 +163,22 @@ class DemoMobileConnectionRepository(
_satelliteLevel
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_SATELLITE_LEVEL,
- _satelliteLevel.value,
+ initialValue = _satelliteLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _satelliteLevel.value)
private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
override val dataConnectionState =
_dataConnectionState
- .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataConnectionState.value)
+ .logDiffsForTable(tableLogBuffer, initialValue = _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)
+ .logDiffsForTable(tableLogBuffer, initialValue = _dataActivityDirection.value)
.stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value)
private val _carrierNetworkChangeActive = MutableStateFlow(false)
@@ -201,9 +186,8 @@ class DemoMobileConnectionRepository(
_carrierNetworkChangeActive
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CARRIER_NETWORK_CHANGE,
- _carrierNetworkChangeActive.value,
+ initialValue = _carrierNetworkChangeActive.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value)
@@ -211,7 +195,7 @@ class DemoMobileConnectionRepository(
MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
override val resolvedNetworkType =
_resolvedNetworkType
- .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value)
+ .logDiffsForTable(tableLogBuffer, initialValue = _resolvedNetworkType.value)
.stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value)
override val numberOfLevels =
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 b608e53b4bce..987173eb122d 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
@@ -39,7 +39,6 @@ import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoMod
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -54,7 +53,6 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
/** This repository vends out data based on demo mode commands */
-@OptIn(ExperimentalCoroutinesApi::class)
class DemoMobileConnectionsRepository
@Inject
constructor(
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 98aa7fa637d9..5094bc7e083a 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
@@ -28,7 +28,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConn
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -46,7 +45,6 @@ import kotlinx.coroutines.flow.stateIn
* carrier merged (see [setIsCarrierMerged]).
*/
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
class FullMobileConnectionRepository(
override val subId: Int,
startingIsCarrierMerged: Boolean,
@@ -75,7 +73,6 @@ class FullMobileConnectionRepository(
_isCarrierMerged
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "isCarrierMerged",
initialValue = startingIsCarrierMerged,
)
@@ -130,9 +127,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.isEmergencyOnly }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_EMERGENCY,
- activeRepo.value.isEmergencyOnly.value,
+ initialValue = activeRepo.value.isEmergencyOnly.value,
)
.stateIn(
scope,
@@ -145,9 +141,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.isRoaming }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_ROAMING,
- activeRepo.value.isRoaming.value,
+ initialValue = activeRepo.value.isRoaming.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isRoaming.value)
@@ -156,9 +151,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.operatorAlphaShort }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_OPERATOR,
- activeRepo.value.operatorAlphaShort.value,
+ initialValue = activeRepo.value.operatorAlphaShort.value,
)
.stateIn(
scope,
@@ -171,9 +165,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.isInService }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_IN_SERVICE,
- activeRepo.value.isInService.value,
+ initialValue = activeRepo.value.isInService.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isInService.value)
@@ -182,9 +175,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.isNonTerrestrial }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_NTN,
- activeRepo.value.isNonTerrestrial.value,
+ initialValue = activeRepo.value.isNonTerrestrial.value,
)
.stateIn(
scope,
@@ -197,9 +189,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.isGsm }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_GSM,
- activeRepo.value.isGsm.value,
+ initialValue = activeRepo.value.isGsm.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isGsm.value)
@@ -208,9 +199,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.cdmaLevel }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CDMA_LEVEL,
- activeRepo.value.cdmaLevel.value,
+ initialValue = activeRepo.value.cdmaLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaLevel.value)
@@ -219,9 +209,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.primaryLevel }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_PRIMARY_LEVEL,
- activeRepo.value.primaryLevel.value,
+ initialValue = activeRepo.value.primaryLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.primaryLevel.value)
@@ -230,9 +219,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.satelliteLevel }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_SATELLITE_LEVEL,
- activeRepo.value.satelliteLevel.value,
+ initialValue = activeRepo.value.satelliteLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.satelliteLevel.value)
@@ -241,8 +229,7 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.dataConnectionState }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
- activeRepo.value.dataConnectionState.value,
+ initialValue = activeRepo.value.dataConnectionState.value,
)
.stateIn(
scope,
@@ -255,8 +242,7 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.dataActivityDirection }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
- activeRepo.value.dataActivityDirection.value,
+ initialValue = activeRepo.value.dataActivityDirection.value,
)
.stateIn(
scope,
@@ -269,9 +255,8 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.carrierNetworkChangeActive }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CARRIER_NETWORK_CHANGE,
- activeRepo.value.carrierNetworkChangeActive.value,
+ initialValue = activeRepo.value.carrierNetworkChangeActive.value,
)
.stateIn(
scope,
@@ -284,8 +269,7 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.resolvedNetworkType }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
- activeRepo.value.resolvedNetworkType.value,
+ initialValue = activeRepo.value.resolvedNetworkType.value,
)
.stateIn(
scope,
@@ -298,7 +282,6 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.dataEnabled }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "dataEnabled",
initialValue = activeRepo.value.dataEnabled.value,
)
@@ -309,7 +292,6 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.inflateSignalStrength }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "inflate",
initialValue = activeRepo.value.inflateSignalStrength.value,
)
@@ -324,7 +306,6 @@ class FullMobileConnectionRepository(
.flatMapLatest { it.allowNetworkSliceIndicator }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "allowSlice",
initialValue = activeRepo.value.allowNetworkSliceIndicator.value,
)
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 d69dc1e06cd6..b4a45e24a0cb 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
@@ -68,7 +68,6 @@ import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -92,7 +91,6 @@ import kotlinx.coroutines.withContext
* connection -- see [CarrierMergedConnectionRepository]).
*/
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
class MobileConnectionRepositoryImpl(
override val subId: Int,
private val context: Context,
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 aa6da61958e0..d3369033942e 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
@@ -62,7 +62,6 @@ import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -81,7 +80,6 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MobileConnectionsRepositoryImpl
@Inject
@@ -382,7 +380,6 @@ constructor(
.distinctUntilChanged()
.logDiffsForTable(
tableLogger,
- columnPrefix = "",
columnName = "defaultConnectionIsValidated",
initialValue = false,
)
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 2a9a199439e6..a1f7a81e258a 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
@@ -36,7 +36,6 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconMod
import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -135,7 +134,6 @@ interface MobileIconInteractor {
/** Interactor for a single mobile connection. This connection _should_ have one subscription ID */
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
class MobileIconInteractorImpl(
@Background scope: CoroutineScope,
defaultSubscriptionHasDataEnabled: StateFlow<Boolean>,
@@ -240,7 +238,6 @@ class MobileIconInteractorImpl(
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogBuffer,
- columnPrefix = "",
initialValue = DefaultIcon(defaultMobileIconGroup.value),
)
.stateIn(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
index be56461a96ee..ac3728d9dcaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
@@ -39,7 +39,6 @@ import com.android.systemui.util.CarrierConfigTracker
import java.lang.ref.WeakReference
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -128,7 +127,6 @@ interface MobileIconsInteractor {
}
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MobileIconsInteractorImpl
@Inject
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 0bd3426712bd..171e4f59b0e5 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
@@ -31,7 +31,6 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.model.MobileContentDesc
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -74,7 +73,6 @@ interface MobileIconViewModelCommon {
* model gets the exact same information, as well as allows us to log that unified state only once
* per icon.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
class MobileIconViewModel(
override val subscriptionId: Int,
iconInteractor: MobileIconInteractor,
@@ -164,7 +162,6 @@ private class CarrierBasedSatelliteViewModelImpl(
/** Terrestrial (cellular) icon. */
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
private class CellularIconViewModel(
override val subscriptionId: Int,
iconInteractor: MobileIconInteractor,
@@ -194,7 +191,6 @@ private class CellularIconViewModel(
.distinctUntilChanged()
.logDiffsForTable(
iconInteractor.tableLogBuffer,
- columnPrefix = "",
columnName = "visible",
initialValue = false,
)
@@ -252,7 +248,6 @@ private class CellularIconViewModel(
.distinctUntilChanged()
.logDiffsForTable(
iconInteractor.tableLogBuffer,
- columnPrefix = "",
columnName = "showNetworkTypeIcon",
initialValue = false,
)
@@ -296,7 +291,6 @@ private class CellularIconViewModel(
iconInteractor.isRoaming
.logDiffsForTable(
iconInteractor.tableLogBuffer,
- columnPrefix = "",
columnName = "roaming",
initialValue = false,
)
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 67fdb3ae7681..22feb7ce77c8 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
@@ -33,7 +33,6 @@ import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.SharingStarted
@@ -49,7 +48,6 @@ import kotlinx.coroutines.flow.stateIn
* of [MobileIconViewModel]s which describe the individual icons and can be bound to
* [ModernStatusBarMobileView].
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MobileIconsViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
index 70abb02a48ce..de2a6459f6ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
@@ -27,7 +27,6 @@ import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteC
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -51,7 +50,6 @@ import kotlinx.coroutines.flow.stateIn
* DemoRepository
* ```
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class DeviceBasedSatelliteRepositorySwitcher
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
index 3a6716ab4c7e..982f6ec36150 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
@@ -54,7 +54,6 @@ import javax.inject.Inject
import kotlin.coroutines.resume
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
@@ -100,7 +99,6 @@ sealed interface SatelliteSupport {
*/
data object NotSupported : SatelliteSupport
- @OptIn(ExperimentalCoroutinesApi::class)
companion object {
/**
* Convenience function to switch to the supported flow. [retrySignal] is a flow that emits
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
index 86f9c94b7989..569e02cc67bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
@@ -32,7 +32,6 @@ import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiIntera
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
@@ -64,12 +63,7 @@ constructor(
flowOf(false)
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- columnName = COL_ALLOWED,
- initialValue = false,
- )
+ .logDiffsForTable(tableLog, columnName = COL_ALLOWED, initialValue = false)
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
/** See [SatelliteConnectionState] for relevant states */
@@ -81,11 +75,7 @@ constructor(
flowOf(SatelliteConnectionState.Off)
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- initialValue = SatelliteConnectionState.Off,
- )
+ .logDiffsForTable(tableLog, initialValue = SatelliteConnectionState.Off)
.stateIn(scope, SharingStarted.WhileSubscribed(), SatelliteConnectionState.Off)
/** 0-4 description of the connection strength */
@@ -96,7 +86,7 @@ constructor(
flowOf(0)
}
.distinctUntilChanged()
- .logDiffsForTable(tableLog, columnPrefix = "", columnName = COL_LEVEL, initialValue = 0)
+ .logDiffsForTable(tableLog, columnName = COL_LEVEL, initialValue = 0)
.stateIn(scope, SharingStarted.WhileSubscribed(), 0)
val isSatelliteProvisioned = repo.isSatelliteProvisioned
@@ -120,12 +110,7 @@ constructor(
isOosAndNotEmergencyAndNotSatellite.all { it }
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- columnName = COL_ALL_OOS,
- initialValue = true,
- )
+ .logDiffsForTable(tableLog, columnName = COL_ALL_OOS, initialValue = true)
/** When all connections are considered OOS, satellite connectivity is potentially valid */
val areAllConnectionsOutOfService =
@@ -153,12 +138,7 @@ constructor(
flowOf(false)
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- columnName = COL_FULL_OOS,
- initialValue = true,
- )
+ .logDiffsForTable(tableLog, columnName = COL_FULL_OOS, initialValue = true)
.stateIn(scope, SharingStarted.WhileSubscribed(), true)
/** True if any known mobile network is currently using a non terrestrial network */
@@ -190,7 +170,6 @@ constructor(
* [defaultValue] allows for a default value to be used if there are no leaf nodes after applying
* [selector]. E.g., if there are no mobile connections, assume that there is no service.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
private inline fun <R, reified S, T> Flow<List<R>>.aggregateOver(
crossinline selector: (R) -> Flow<S>,
defaultValue: T,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
index ea915efb17be..270a28ecd6ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
@@ -34,7 +34,6 @@ import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconM
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -62,7 +61,6 @@ interface DeviceBasedSatelliteViewModel {
val carrierText: StateFlow<String?>
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class DeviceBasedSatelliteViewModelImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt
index b94ef03abdde..54916b216589 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt
@@ -22,7 +22,6 @@ import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.Airpla
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.CarrierConfigInteractor
import com.android.systemui.statusbar.pipeline.shared.domain.model.StatusBarDisableFlagsVisibilityModel
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
@@ -33,7 +32,6 @@ import kotlinx.coroutines.flow.map
* Interactor for the home screen status bar (aka
* [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment]).
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class HomeStatusBarInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
index 5acedf129184..a59d95f27c38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
@@ -195,7 +195,6 @@ constructor(
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_LOCK_TO_OCCLUDED,
initialValue = false,
)
@@ -228,7 +227,6 @@ constructor(
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_ALLOWED_BY_SCENE,
initialValue = false,
)
@@ -248,7 +246,6 @@ constructor(
}
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_NOTIF_LIGHTS_OUT,
initialValue = false,
)
@@ -306,7 +303,6 @@ constructor(
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_VISIBLE,
initialValue = false,
)
@@ -350,7 +346,6 @@ constructor(
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_SHOW_OPERATOR_NAME,
initialValue = false,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt
index 352413ee568a..6258a55c374f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt
@@ -38,7 +38,6 @@ import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkMode
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -52,7 +51,6 @@ import kotlinx.coroutines.flow.stateIn
* InternetTileModel objects, so that updating the tile is as simple as collecting on this state
* flow and then calling [QSTileImpl.refreshState]
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class InternetTileViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt
index 0b83c4e3dea3..6ea5fe401dea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -28,7 +27,6 @@ import kotlinx.coroutines.flow.flowOf
* View model for the operator name (aka carrier name) of the carrier for the default data
* subscription.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class StatusBarOperatorNameViewModel
@Inject
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 b6e01e86b7d5..8d1edd9cada4 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
@@ -29,7 +29,6 @@ import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -54,7 +53,6 @@ import kotlinx.coroutines.flow.stateIn
* that flow.
*/
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class WifiRepositorySwitcher
@Inject
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 6ed2ce82b968..f9bba9d624f1 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
@@ -109,7 +109,6 @@ constructor(
secondaryNetworks = emptyList(),
)
- @kotlinx.coroutines.ExperimentalCoroutinesApi
private val wifiPickerTrackerInfo: StateFlow<WifiPickerTrackerInfo> =
if (multiuserWifiPickerTrackerSupport()) {
selectedUserContext
@@ -301,19 +300,14 @@ constructor(
wifiPickerTrackerInfo
.map { it.state == WifiManager.WIFI_STATE_ENABLED }
.distinctUntilChanged()
- .logDiffsForTable(
- tableLogger,
- columnPrefix = "",
- columnName = COL_NAME_IS_ENABLED,
- initialValue = false,
- )
+ .logDiffsForTable(tableLogger, columnName = COL_NAME_IS_ENABLED, initialValue = false)
.stateIn(scope, SharingStarted.Eagerly, false)
override val wifiNetwork: StateFlow<WifiNetworkModel> =
wifiPickerTrackerInfo
.map { it.primaryNetwork }
.distinctUntilChanged()
- .logDiffsForTable(tableLogger, columnPrefix = "", initialValue = WIFI_NETWORK_DEFAULT)
+ .logDiffsForTable(tableLogger, initialValue = WIFI_NETWORK_DEFAULT)
.stateIn(scope, SharingStarted.Eagerly, WIFI_NETWORK_DEFAULT)
override val secondaryNetworks: StateFlow<List<WifiNetworkModel>> =
@@ -322,7 +316,6 @@ constructor(
.distinctUntilChanged()
.logDiffsForTable(
tableLogger,
- columnPrefix = "",
columnName = "secondaryNetworks",
initialValue = emptyList(),
)
@@ -401,12 +394,7 @@ constructor(
wifiPickerTrackerInfo
.map { it.isDefault }
.distinctUntilChanged()
- .logDiffsForTable(
- tableLogger,
- columnPrefix = "",
- columnName = COL_NAME_IS_DEFAULT,
- initialValue = false,
- )
+ .logDiffsForTable(tableLogger, columnName = COL_NAME_IS_DEFAULT, initialValue = false)
.stateIn(scope, SharingStarted.Eagerly, false)
override val wifiActivity: StateFlow<DataActivityModel> =
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 f9556d2e8003..986068bc00bc 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
@@ -89,7 +89,7 @@ constructor(
else -> WifiIcon.Hidden
}
}
- .logDiffsForTable(wifiTableLogBuffer, columnPrefix = "", initialValue = WifiIcon.Hidden)
+ .logDiffsForTable(wifiTableLogBuffer, initialValue = WifiIcon.Hidden)
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index 23e40b220a68..90d21b588ef0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -17,11 +17,8 @@
package com.android.systemui.statusbar.policy;
import android.app.NotificationManager;
-import android.content.ComponentName;
import android.net.Uri;
-import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
-import android.service.notification.ZenModeConfig.ZenRule;
import com.android.systemui.statusbar.policy.ZenModeController.Callback;
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor;
@@ -35,25 +32,17 @@ import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
public interface ZenModeController extends CallbackController<Callback> {
void setZen(int zen, Uri conditionId, String reason);
int getZen();
- ZenRule getManualRule();
ZenModeConfig getConfig();
/** Gets consolidated zen policy that will apply when DND is on in priority only mode */
NotificationManager.Policy getConsolidatedPolicy();
long getNextAlarm();
boolean isZenAvailable();
- ComponentName getEffectsSuppressor();
- boolean isCountdownConditionSupported();
int getCurrentUser();
- boolean isVolumeRestricted();
- boolean areNotificationsHiddenInShade();
public static interface Callback {
default void onZenChanged(int zen) {}
- default void onConditionsChanged(Condition[] conditions) {}
default void onNextAlarmChanged() {}
default void onZenAvailableChanged(boolean available) {}
- default void onEffectsSupressorChanged() {}
- default void onManualRuleChanged(ZenRule rule) {}
default void onConfigChanged(ZenModeConfig config) {}
/** Called when the consolidated zen policy changes */
default void onConsolidatedPolicyChanged(NotificationManager.Policy policy) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 0cba94016ffb..9ad8619faacc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -20,7 +20,6 @@ import android.app.AlarmManager;
import android.app.Flags;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -35,7 +34,6 @@ import android.os.UserManager;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.service.notification.ZenModeConfig;
-import android.service.notification.ZenModeConfig.ZenRule;
import android.text.format.DateFormat;
import android.util.Log;
@@ -92,7 +90,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
}
final IntentFilter filter = new IntentFilter(
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
- filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
mBroadcastDispatcher.registerReceiver(mReceiver, filter, null,
UserHandle.of(mUserId));
mRegistered = true;
@@ -156,21 +153,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
}
@Override
- public boolean isVolumeRestricted() {
- return mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME,
- UserHandle.of(mUserId));
- }
-
- @Override
- public boolean areNotificationsHiddenInShade() {
- if (mZenMode != Global.ZEN_MODE_OFF) {
- return (mConsolidatedNotificationPolicy.suppressedVisualEffects
- & NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST) != 0;
- }
- return false;
- }
-
- @Override
public void addCallback(@NonNull Callback callback) {
synchronized (mCallbacksLock) {
Log.d(TAG, "Added callback " + callback.getClass());
@@ -206,11 +188,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
}
@Override
- public ZenRule getManualRule() {
- return mConfig == null ? null : mConfig.manualRule;
- }
-
- @Override
public ZenModeConfig getConfig() {
return mConfig;
}
@@ -228,17 +205,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
}
@Override
- public ComponentName getEffectsSuppressor() {
- return NotificationManager.from(mContext).getEffectsSuppressor();
- }
-
- @Override
- public boolean isCountdownConditionSupported() {
- return NotificationManager.from(mContext)
- .isSystemConditionProviderEnabled(ZenModeConfig.COUNTDOWN_PATH);
- }
-
- @Override
public int getCurrentUser() {
return mUserTracker.getUserId();
}
@@ -247,10 +213,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
fireSafeChange(Callback::onNextAlarmChanged);
}
- private void fireEffectsSuppressorChanged() {
- fireSafeChange(Callback::onEffectsSupressorChanged);
- }
-
private void fireZenChanged(int zen) {
fireSafeChange(c -> c.onZenChanged(zen));
}
@@ -259,10 +221,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
fireSafeChange(c -> c.onZenAvailableChanged(available));
}
- private void fireManualRuleChanged(ZenRule rule) {
- fireSafeChange(c -> c.onManualRuleChanged(rule));
- }
-
private void fireConsolidatedPolicyChanged(NotificationManager.Policy policy) {
fireSafeChange(c -> c.onConsolidatedPolicyChanged(policy));
}
@@ -302,16 +260,10 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
protected void updateZenModeConfig() {
final ZenModeConfig config = mNoMan.getZenModeConfig();
if (Objects.equals(config, mConfig)) return;
- final ZenRule oldRule = mConfig != null ? mConfig.manualRule : null;
mConfig = config;
mZenUpdateTime = System.currentTimeMillis();
fireConfigChanged(config);
- final ZenRule newRule = config != null ? config.manualRule : null;
- if (!Objects.equals(oldRule, newRule)) {
- fireManualRuleChanged(newRule);
- }
-
final NotificationManager.Policy consolidatedPolicy =
mNoMan.getConsolidatedNotificationPolicy();
if (!Objects.equals(consolidatedPolicy, mConsolidatedNotificationPolicy)) {
@@ -327,9 +279,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
fireNextAlarmChanged();
}
- if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
- fireEffectsSuppressorChanged();
- }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt
index 73cdf48ce58f..82d57f29c5cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt
@@ -23,7 +23,6 @@ import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -41,7 +40,6 @@ interface UserSetupRepository {
val isUserSetUp: StateFlow<Boolean>
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class UserSetupRepositoryImpl
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt
index 69b7e892a380..9795cda97f37 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt
@@ -49,8 +49,10 @@ import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.android.systemui.inputdevice.tutorial.ui.composable.DoneButton
+import com.android.systemui.keyboard.shortcut.ui.composable.hasCompactWindowSize
import com.android.systemui.res.R
import com.android.systemui.touchpad.tutorial.ui.gesture.isFourFingerTouchpadSwipe
import com.android.systemui.touchpad.tutorial.ui.gesture.isThreeFingerTouchpadSwipe
@@ -80,6 +82,7 @@ fun TutorialSelectionScreen(
}
),
) {
+ val padding = if (hasCompactWindowSize()) 24.dp else 60.dp
val configuration = LocalConfiguration.current
when (configuration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> {
@@ -88,7 +91,7 @@ fun TutorialSelectionScreen(
onHomeTutorialClicked = onHomeTutorialClicked,
onRecentAppsTutorialClicked = onRecentAppsTutorialClicked,
onSwitchAppsTutorialClicked = onSwitchAppsTutorialClicked,
- modifier = Modifier.weight(1f).padding(60.dp),
+ modifier = Modifier.weight(1f).padding(padding),
lastSelectedScreen,
)
}
@@ -98,7 +101,7 @@ fun TutorialSelectionScreen(
onHomeTutorialClicked = onHomeTutorialClicked,
onRecentAppsTutorialClicked = onRecentAppsTutorialClicked,
onSwitchAppsTutorialClicked = onSwitchAppsTutorialClicked,
- modifier = Modifier.weight(1f).padding(60.dp),
+ modifier = Modifier.weight(1f).padding(padding),
lastSelectedScreen,
)
}
@@ -106,7 +109,7 @@ fun TutorialSelectionScreen(
// because other composables have weight 1, Done button will be positioned first
DoneButton(
onDoneButtonClicked = onDoneButtonClicked,
- modifier = Modifier.padding(horizontal = 60.dp),
+ modifier = Modifier.padding(horizontal = padding),
)
}
}
@@ -146,7 +149,7 @@ private fun VerticalSelectionButtons(
lastSelectedScreen: Screen,
) {
Column(
- verticalArrangement = Arrangement.spacedBy(20.dp),
+ verticalArrangement = Arrangement.spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier,
) {
@@ -244,8 +247,13 @@ private fun TutorialButton(
modifier = Modifier.width(30.dp).height(30.dp),
tint = iconColor,
)
- Spacer(modifier = Modifier.height(16.dp))
- Text(text = text, style = MaterialTheme.typography.headlineLarge, color = iconColor)
+ if (!hasCompactWindowSize()) Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = text,
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.headlineLarge,
+ color = iconColor,
+ )
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/GestureRecognizerAdapter.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/GestureRecognizerAdapter.kt
index 8e7375fa923b..a9dcdffbbf83 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/GestureRecognizerAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/GestureRecognizerAdapter.kt
@@ -25,7 +25,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.util.function.Consumer
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
@@ -43,7 +42,6 @@ constructor(
private var gestureRecognizer: GestureRecognizer? = null
- @OptIn(ExperimentalCoroutinesApi::class)
val gestureState: Flow<GestureState> =
provider.recognizer.flatMapLatest {
gestureRecognizer = it
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
index dccd5900963c..f5aac720fd47 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
@@ -46,7 +46,6 @@ import java.time.Duration
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.flow.filter
@@ -81,7 +80,6 @@ constructor(
private val isAodEnabled: Boolean
get() = keyguardInteractor.isAodAvailable.value
- @OptIn(ExperimentalCoroutinesApi::class)
override fun start() {
if (!isDeviceFoldable(context.resources, deviceStateManager)) {
return
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
index ecc2f18c7bcd..f99094784e63 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimation.kt
@@ -58,7 +58,6 @@ import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
-@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
class FoldLightRevealOverlayAnimation
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt
index 53c2d888922b..af652837869a 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt
@@ -22,12 +22,10 @@ import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Text
import com.android.systemui.user.domain.interactor.UserSwitcherInteractor
import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapLatest
-@OptIn(ExperimentalCoroutinesApi::class)
class StatusBarUserChipViewModel
@Inject
constructor(private val interactor: UserSwitcherInteractor) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/repository/UserAwareSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/util/settings/repository/UserAwareSettingsRepository.kt
index af03c529cb52..73329b467c04 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/repository/UserAwareSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/repository/UserAwareSettingsRepository.kt
@@ -22,7 +22,6 @@ import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import com.android.systemui.util.settings.UserSettingsProxy
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
@@ -37,7 +36,6 @@ import kotlinx.coroutines.withContext
* the new value.
*/
// TODO: b/377244768 - Make internal when UserAwareSecureSettingsRepository can be made internal.
-@OptIn(ExperimentalCoroutinesApi::class)
abstract class UserAwareSettingsRepository(
private val userSettings: UserSettingsProxy,
private val userRepository: UserRepository,
diff --git a/packages/SystemUI/src/com/android/systemui/util/ui/AnimatedValue.kt b/packages/SystemUI/src/com/android/systemui/util/ui/AnimatedValue.kt
index a5c8af588667..8079f1ee2472 100644
--- a/packages/SystemUI/src/com/android/systemui/util/ui/AnimatedValue.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/ui/AnimatedValue.kt
@@ -13,14 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.util.ui
import com.android.systemui.util.ui.AnimatedValue.Animating
import com.android.systemui.util.ui.AnimatedValue.NotAnimating
import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.transformLatest
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt
index 203a157f6ffc..5a69be5486a0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt
@@ -28,13 +28,11 @@ import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogPluginViewMod
import javax.inject.Inject
import kotlin.coroutines.resume
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.suspendCancellableCoroutine
-@OptIn(ExperimentalCoroutinesApi::class)
class VolumeDialogPlugin
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt
index 7307807adb74..20a74b027db5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt
@@ -31,7 +31,6 @@ import javax.inject.Inject
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -52,7 +51,6 @@ private val MAX_DIALOG_SHOW_TIME: Duration = 3.seconds
* - it might be dismissed by the inactivity timeout;
* - it can be dismissed by the user;
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumeDialogPluginScope
class VolumeDialogVisibilityInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
index 908249dbca08..2af4b61ee6c4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
@@ -43,7 +43,6 @@ import com.android.systemui.volume.dialog.ui.utils.suspendAnimate
import javax.inject.Inject
import kotlin.properties.Delegates
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
@@ -54,7 +53,6 @@ private const val CLOSE_DRAWER_DELAY = 300L
// Ensure roundness and color of button is updated when progress is changed by a minimum fraction.
private const val BUTTON_MIN_VISIBLE_CHANGE = 0.05F
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumeDialogScope
class VolumeDialogRingerViewBinder
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt
index 03442dbcde66..0e4e707df923 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.volume.dialog.settings.ui.viewmodel
import android.animation.Animator
@@ -47,7 +45,6 @@ import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt
index 0fdf5d6266d0..9c97637ce52e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt
@@ -26,7 +26,6 @@ import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.sign
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -38,7 +37,6 @@ import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.transform
@VolumeDialogSliderScope
-@OptIn(ExperimentalCoroutinesApi::class)
class VolumeDialogOverscrollViewModel
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt
index e89d5ab53560..9ac052af95d9 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt
@@ -33,7 +33,6 @@ import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
import javax.inject.Inject
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -58,7 +57,6 @@ import kotlinx.coroutines.flow.stateIn
// TODO(b/375355785) remove this
private const val VOLUME_UPDATE_GRACE_PERIOD = 1000
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumeDialogSliderScope
class VolumeDialogSliderViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
index 428dc6ecb5b6..b8c0fc048c28 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
@@ -45,7 +45,6 @@ import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
import com.android.systemui.volume.dialog.utils.VolumeTracer
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
@@ -56,7 +55,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
/** Binds the root view of the Volume Dialog. */
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumeDialogScope
class VolumeDialogViewBinder
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt
index 9bab1b0aa25d..e7a2cf4eff08 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt
@@ -27,12 +27,10 @@ import com.android.systemui.volume.dialog.shared.model.VolumeDialogVisibilityMod
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.mapLatest
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumeDialogPluginScope
class VolumeDialogPluginViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
index 73728e698c09..4dbdba12c1b3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
@@ -35,7 +35,6 @@ import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
@@ -45,7 +44,6 @@ import kotlinx.coroutines.flow.stateIn
/** Provides a currently active audio device data. */
@VolumePanelScope
-@OptIn(ExperimentalCoroutinesApi::class)
class AudioOutputInteractor
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt
index cfff45736159..e95a09a9874c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/domain/interactor/AncSliceInteractor.kt
@@ -26,7 +26,6 @@ import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -38,7 +37,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
/** Provides a valid slice from [AncSliceRepository]. */
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumePanelScope
class AncSliceInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
index c980eb43ec97..7d811342764e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/anc/ui/viewmodel/AncViewModel.kt
@@ -25,7 +25,6 @@ import com.android.systemui.volume.panel.component.anc.domain.model.AncSlices
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -34,7 +33,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Volume Panel ANC component view model. */
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumePanelScope
class AncViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt
index 12e624cae4d4..8253872a277b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt
@@ -25,7 +25,6 @@ import com.android.systemui.volume.panel.component.mediaoutput.domain.model.Medi
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.filterIsInstance
@@ -37,7 +36,6 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext
/** Allows to observe and change [MediaDeviceSession] state. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MediaDeviceSessionInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt
index 609ba0212cef..fbb544e73b98 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt
@@ -31,7 +31,6 @@ import com.android.systemui.volume.panel.shared.model.filterData
import com.android.systemui.volume.panel.shared.model.wrapInResult
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -44,7 +43,6 @@ import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.stateIn
/** Gathers together a domain state for the Media Output Volume Panel component. */
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumePanelScope
class MediaOutputComponentInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index 2973e11c365d..1bb186b73881 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -37,7 +37,6 @@ import com.android.systemui.volume.panel.shared.model.wrapInResult
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -54,7 +53,6 @@ import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.withContext
/** Provides observable models about the current media session state. */
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class MediaOutputInteractor
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
index 6c4a853b42ad..f6edd472d005 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
@@ -34,14 +34,12 @@ import com.android.systemui.volume.panel.shared.model.filterData
import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Models the UI of the Media Output Volume Panel component. */
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumePanelScope
class MediaOutputViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioSharingStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioSharingStreamSliderViewModel.kt
index 4ce9fe561aed..5f20b4e27a80 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioSharingStreamSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioSharingStreamSliderViewModel.kt
@@ -29,7 +29,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -39,7 +38,6 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
-@OptIn(ExperimentalCoroutinesApi::class)
class AudioSharingStreamSliderViewModel
@AssistedInject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
index 28f11050fa4a..0813eac9459e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
@@ -32,7 +32,6 @@ import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import com.android.systemui.volume.panel.shared.model.filterData
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -52,7 +51,6 @@ import kotlinx.coroutines.flow.transformLatest
* Controls the behaviour of the whole audio
* [com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent].
*/
-@OptIn(ExperimentalCoroutinesApi::class)
@VolumePanelScope
class AudioVolumeComponentViewModel
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
index 2f60c4b29a81..f52693a62608 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt
@@ -42,7 +42,6 @@ import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
@@ -56,7 +55,6 @@ private const val TAG = "VolumePanelViewModel"
// Can't inject a constructor here because VolumePanelComponent provides this view model for its
// components.
-@OptIn(ExperimentalCoroutinesApi::class)
class VolumePanelViewModel(
resources: Resources,
coroutineScope: CoroutineScope,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt b/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
index e590a7de09ad..680cf76180d4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/ui/navigation/VolumeNavigator.kt
@@ -40,7 +40,6 @@ import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emptyFlow
@@ -49,7 +48,6 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class VolumeNavigator
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt b/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt
index af84e4eaf0c5..594c5526dca9 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt
@@ -31,7 +31,6 @@ import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -45,7 +44,6 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import com.android.app.tracing.coroutines.launchTraced as launch
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class WalletContextualSuggestionsController
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt
index 760e94c72f19..33e1929ebf8b 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/GradientColorWallpaper.kt
@@ -19,10 +19,14 @@ package com.android.systemui.wallpapers
import android.app.Flags
import android.graphics.Canvas
import android.graphics.Paint
+import android.graphics.RadialGradient
+import android.graphics.Shader
import android.service.wallpaper.WallpaperService
import android.util.Log
import android.view.SurfaceHolder
+import androidx.core.graphics.ColorUtils
import androidx.core.graphics.toRectF
+import com.android.systemui.res.R
/** A wallpaper that shows a static gradient color image wallpaper. */
class GradientColorWallpaper : WallpaperService() {
@@ -54,9 +58,60 @@ class GradientColorWallpaper : WallpaperService() {
canvas = surface.lockHardwareCanvas()
val destRectF = surfaceHolder.surfaceFrame.toRectF()
val toColor = context.getColor(com.android.internal.R.color.materialColorPrimary)
+ val fromColor =
+ ColorUtils.setAlphaComponent(
+ context.getColor(
+ com.android.internal.R.color.materialColorPrimaryContainer
+ ),
+ /* alpha= */ 153, // 0.6f * 255
+ )
- // TODO(b/384519696): Draw the actual gradient color wallpaper instead.
canvas.drawRect(destRectF, Paint().apply { color = toColor })
+
+ val offsetPx: Float =
+ context.resources
+ .getDimensionPixelSize(R.dimen.gradient_color_wallpaper_center_offset)
+ .toFloat()
+ val totalHeight = destRectF.height() + (offsetPx * 2)
+ val leftCenterX = -offsetPx
+ val leftCenterY = -offsetPx
+ val rightCenterX = offsetPx + destRectF.width()
+ val rightCenterY = totalHeight - offsetPx
+ val radius = (destRectF.width() / 2) + offsetPx
+
+ canvas.drawCircle(
+ leftCenterX,
+ leftCenterY,
+ radius,
+ Paint().apply {
+ shader =
+ RadialGradient(
+ /* centerX= */ leftCenterX,
+ /* centerY= */ leftCenterY,
+ /* radius= */ radius,
+ /* centerColor= */ fromColor,
+ /* edgeColor= */ toColor,
+ /* tileMode= */ Shader.TileMode.CLAMP,
+ )
+ },
+ )
+
+ canvas.drawCircle(
+ rightCenterX,
+ rightCenterY,
+ radius,
+ Paint().apply {
+ shader =
+ RadialGradient(
+ /* centerX= */ rightCenterX,
+ /* centerY= */ rightCenterY,
+ /* radius= */ radius,
+ /* centerColor= */ fromColor,
+ /* edgeColor= */ toColor,
+ /* tileMode= */ Shader.TileMode.CLAMP,
+ )
+ },
+ )
} catch (exception: IllegalStateException) {
Log.d(TAG, "Fail to draw in the canvas", exception)
} finally {
diff --git a/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt b/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
index 8e0616c00196..bfa349876c42 100644
--- a/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
@@ -18,6 +18,7 @@ package com.android.systemui.window.domain.interactor
import android.util.Log
import com.android.systemui.Flags
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -46,6 +47,7 @@ constructor(
@Application private val applicationScope: CoroutineScope,
private val keyguardInteractor: KeyguardInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ private val communalInteractor: CommunalInteractor,
private val repository: WindowRootViewBlurRepository,
) {
private var isBouncerTransitionInProgress: StateFlow<Boolean> =
@@ -87,6 +89,23 @@ constructor(
}
/**
+ * Request to apply blur while on glanceable hub, this takes precedence over other blurs (from
+ * shade) except for bouncer.
+ */
+ fun requestBlurForGlanceableHub(blurRadius: Int): Boolean {
+ if (keyguardInteractor.primaryBouncerShowing.value) {
+ return false
+ }
+
+ Log.d(TAG, "requestBlurForGlanceableHub for $blurRadius")
+
+ repository.isBlurOpaque.value = false
+ repository.blurRadius.value = blurRadius
+
+ return true
+ }
+
+ /**
* Method that requests blur to be applied on window root view. It is applied only when other
* blurs are not applied.
*
@@ -103,6 +122,9 @@ constructor(
if (keyguardInteractor.primaryBouncerShowing.value || isBouncerTransitionInProgress.value) {
return false
}
+ if (communalInteractor.isCommunalBlurring.value) {
+ return false
+ }
Log.d(TAG, "requestingBlurForShade for $blurRadius $opaque")
repository.blurRadius.value = blurRadius
repository.isBlurOpaque.value = opaque
diff --git a/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
index dbccc1d8cca4..e09a74cd0ad3 100644
--- a/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
@@ -26,6 +26,7 @@ import com.android.systemui.lifecycle.viewModel
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.window.ui.viewmodel.WindowRootViewModel
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -42,11 +43,12 @@ object WindowRootViewBinder {
viewModelFactory: WindowRootViewModel.Factory,
blurUtils: BlurUtils?,
choreographer: Choreographer?,
+ mainDispatcher: CoroutineDispatcher,
) {
- if (!Flags.bouncerUiRevamp()) return
+ if (!Flags.bouncerUiRevamp() && !Flags.glanceableHubBlurredBackground()) return
if (blurUtils == null || choreographer == null) return
- view.repeatWhenAttached {
+ view.repeatWhenAttached(mainDispatcher) {
Log.d(TAG, "Binding root view")
var frameCallbackPendingExecution: FrameCallback? = null
view.viewModel(
diff --git a/packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt
index 199d02d267ed..72cca75df92c 100644
--- a/packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt
@@ -19,6 +19,8 @@ package com.android.systemui.window.ui.viewmodel
import android.os.Build
import android.util.Log
import com.android.app.tracing.coroutines.launchTraced
+import com.android.systemui.Flags.glanceableHubBlurredBackground
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubTransition
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
@@ -40,6 +42,7 @@ class WindowRootViewModel
@AssistedInject
constructor(
private val primaryBouncerTransitions: Set<@JvmSuppressWildcards PrimaryBouncerTransition>,
+ private val glanceableHubTransitions: Set<@JvmSuppressWildcards GlanceableHubTransition>,
private val blurInteractor: WindowRootViewBlurInteractor,
) : ExclusiveActivatable() {
@@ -80,6 +83,26 @@ constructor(
blurInteractor.requestBlurForBouncer(blurRadius.toInt())
}
}
+
+ if (glanceableHubBlurredBackground()) {
+ launchTraced("WindowRootViewModel#glanceableHubTransitions") {
+ glanceableHubTransitions
+ .map { transition ->
+ transition.windowBlurRadius.onEach { blurRadius ->
+ if (isLoggable) {
+ Log.d(
+ TAG,
+ "${transition.javaClass.simpleName} windowBlurRadius $blurRadius",
+ )
+ }
+ }
+ }
+ .merge()
+ .collect { blurRadius ->
+ blurInteractor.requestBlurForGlanceableHub(blurRadius.toInt())
+ }
+ }
+ }
}
awaitCancellation()
}
diff --git a/packages/SystemUI/src/com/google/android/systemui/lowlightclock/LowLightClockDreamService.java b/packages/SystemUI/src/com/google/android/systemui/lowlightclock/LowLightClockDreamService.java
new file mode 100644
index 000000000000..8a5f7eaf8776
--- /dev/null
+++ b/packages/SystemUI/src/com/google/android/systemui/lowlightclock/LowLightClockDreamService.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.systemui.lowlightclock;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
+import android.service.dreams.DreamService;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextClock;
+import android.widget.TextView;
+
+import com.android.dream.lowlight.LowLightTransitionCoordinator;
+import com.android.systemui.lowlightclock.ChargingStatusProvider;
+import com.android.systemui.lowlightclock.LowLightClockAnimationProvider;
+import com.android.systemui.lowlightclock.LowLightDisplayController;
+import com.android.systemui.res.R;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+/**
+ * A dark themed text clock dream to be shown when the device is in a low light environment.
+ */
+public class LowLightClockDreamService extends DreamService implements
+ LowLightTransitionCoordinator.LowLightExitListener {
+ private static final String TAG = "LowLightClockDreamService";
+
+ private final ChargingStatusProvider mChargingStatusProvider;
+ private final LowLightDisplayController mDisplayController;
+ private final LowLightClockAnimationProvider mAnimationProvider;
+ private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
+ private boolean mIsDimBrightnessSupported = false;
+
+ private TextView mChargingStatusTextView;
+ private TextClock mTextClock;
+ @Nullable
+ private Animator mAnimationIn;
+ @Nullable
+ private Animator mAnimationOut;
+
+ @Inject
+ public LowLightClockDreamService(
+ ChargingStatusProvider chargingStatusProvider,
+ LowLightClockAnimationProvider animationProvider,
+ LowLightTransitionCoordinator lowLightTransitionCoordinator,
+ Optional<Provider<LowLightDisplayController>> displayController) {
+ super();
+
+ mAnimationProvider = animationProvider;
+ mDisplayController = displayController.map(Provider::get).orElse(null);
+ mChargingStatusProvider = chargingStatusProvider;
+ mLowLightTransitionCoordinator = lowLightTransitionCoordinator;
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ setInteractive(false);
+ setFullscreen(true);
+
+ setContentView(LayoutInflater.from(getApplicationContext()).inflate(
+ R.layout.low_light_clock_dream, null));
+
+ mTextClock = findViewById(R.id.low_light_text_clock);
+
+ mChargingStatusTextView = findViewById(R.id.charging_status_text_view);
+
+ mChargingStatusProvider.startUsing(this::updateChargingMessage);
+
+ mLowLightTransitionCoordinator.setLowLightExitListener(this);
+ }
+
+ @Override
+ public void onDreamingStarted() {
+ mAnimationIn = mAnimationProvider.provideAnimationIn(mTextClock, mChargingStatusTextView);
+ mAnimationIn.start();
+
+ if (mDisplayController != null) {
+ mIsDimBrightnessSupported = mDisplayController.isDisplayBrightnessModeSupported();
+
+ if (mIsDimBrightnessSupported) {
+ Log.v(TAG, "setting dim brightness state");
+ mDisplayController.setDisplayBrightnessModeEnabled(true);
+ } else {
+ Log.v(TAG, "dim brightness not supported");
+ }
+ }
+ }
+
+ @Override
+ public void onDreamingStopped() {
+ if (mIsDimBrightnessSupported) {
+ Log.v(TAG, "clearing dim brightness state");
+ mDisplayController.setDisplayBrightnessModeEnabled(false);
+ }
+ }
+
+ @Override
+ public void onWakeUp() {
+ if (mAnimationIn != null) {
+ mAnimationIn.cancel();
+ }
+ mAnimationOut = mAnimationProvider.provideAnimationOut(mTextClock, mChargingStatusTextView);
+ mAnimationOut.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ LowLightClockDreamService.super.onWakeUp();
+ }
+ });
+ mAnimationOut.start();
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ if (mAnimationOut != null) {
+ mAnimationOut.cancel();
+ }
+
+ mChargingStatusProvider.stopUsing();
+
+ mLowLightTransitionCoordinator.setLowLightExitListener(null);
+ }
+
+ private void updateChargingMessage(boolean showChargingStatus, String chargingStatusMessage) {
+ mChargingStatusTextView.setText(chargingStatusMessage);
+ mChargingStatusTextView.setVisibility(showChargingStatus ? View.VISIBLE : View.INVISIBLE);
+ }
+
+ @Override
+ public Animator onBeforeExitLowLight() {
+ mAnimationOut = mAnimationProvider.provideAnimationOut(mTextClock, mChargingStatusTextView);
+ mAnimationOut.start();
+
+ // Return the animator so that the transition coordinator waits for the low light 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 mAnimationOut;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
index 057ddcd54e68..8bfd2545ff2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
@@ -21,7 +21,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_
import static com.android.systemui.accessibility.AccessibilityLogger.MagnificationSettingsEvent;
import static com.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize;
-import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
+import static com.android.systemui.recents.LauncherProxyService.LauncherProxyListener;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
import static org.mockito.ArgumentMatchers.any;
@@ -53,7 +53,7 @@ import androidx.test.filters.SmallTest;
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.util.settings.SecureSettings;
@@ -80,13 +80,13 @@ public class MagnificationTest extends SysuiTestCase {
@Mock
private IMagnificationConnectionCallback mConnectionCallback;
@Mock
- private OverviewProxyService mOverviewProxyService;
+ private LauncherProxyService mLauncherProxyService;
@Mock
private SecureSettings mSecureSettings;
private CommandQueue mCommandQueue;
private MagnificationImpl mMagnification;
- private OverviewProxyListener mOverviewProxyListener;
+ private LauncherProxyListener mLauncherProxyListener;
private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
@Mock
@@ -130,7 +130,7 @@ public class MagnificationTest extends SysuiTestCase {
mMagnification = new MagnificationImpl(getContext(),
getContext().getMainThreadHandler(), mContext.getMainExecutor(),
mCommandQueue, mModeSwitchesController,
- mSysUiState, mOverviewProxyService, mSecureSettings, mDisplayTracker,
+ mSysUiState, mLauncherProxyService, mSecureSettings, mDisplayTracker,
getContext().getSystemService(DisplayManager.class), mA11yLogger, mIWindowManager,
getContext().getSystemService(AccessibilityManager.class),
mViewCaptureAwareWindowManager);
@@ -140,10 +140,10 @@ public class MagnificationTest extends SysuiTestCase {
mContext.getSystemService(DisplayManager.class), mMagnificationSettingsController);
mMagnification.start();
- final ArgumentCaptor<OverviewProxyListener> listenerArgumentCaptor =
- ArgumentCaptor.forClass(OverviewProxyListener.class);
- verify(mOverviewProxyService).addCallback(listenerArgumentCaptor.capture());
- mOverviewProxyListener = listenerArgumentCaptor.getValue();
+ final ArgumentCaptor<LauncherProxyListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(LauncherProxyListener.class);
+ verify(mLauncherProxyService).addCallback(listenerArgumentCaptor.capture());
+ mLauncherProxyListener = listenerArgumentCaptor.getValue();
}
@Test
@@ -336,7 +336,7 @@ public class MagnificationTest extends SysuiTestCase {
@Test
public void overviewProxyIsConnected_noController_resetFlag() {
- mOverviewProxyListener.onConnectionChanged(true);
+ mLauncherProxyListener.onConnectionChanged(true);
verify(mSysUiState).setFlag(SYSUI_STATE_MAGNIFICATION_OVERLAP, false);
verify(mSysUiState).commitUpdate(mContext.getDisplayId());
@@ -349,7 +349,7 @@ public class MagnificationTest extends SysuiTestCase {
mContext.getSystemService(DisplayManager.class), mController);
mMagnification.mWindowMagnificationControllerSupplier.get(TEST_DISPLAY);
- mOverviewProxyListener.onConnectionChanged(true);
+ mLauncherProxyListener.onConnectionChanged(true);
verify(mController).updateSysUIStateFlag();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
index 222a7fe05778..418972055324 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
@@ -81,6 +81,7 @@ class DefaultDeviceEntrySectionTest : SysuiTestCase() {
{ falsingManager },
{ mock(VibratorHelper::class.java) },
logcatLogBuffer(),
+ logcatLogBuffer("blueprints"),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/AmbientLightModeMonitorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/AmbientLightModeMonitorTest.kt
new file mode 100644
index 000000000000..43ee388e44a7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/AmbientLightModeMonitorTest.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock
+
+import android.hardware.Sensor
+import android.hardware.SensorEventListener
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.sensors.AsyncSensorManager
+import java.util.Optional
+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.any
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class AmbientLightModeMonitorTest : SysuiTestCase() {
+ @Mock private lateinit var sensorManager: AsyncSensorManager
+ @Mock private lateinit var sensor: Sensor
+ @Mock private lateinit var algorithm: AmbientLightModeMonitor.DebounceAlgorithm
+
+ private lateinit var ambientLightModeMonitor: AmbientLightModeMonitor
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ ambientLightModeMonitor =
+ AmbientLightModeMonitor(Optional.of(algorithm), sensorManager, Optional.of(sensor))
+ }
+
+ @Test
+ fun shouldRegisterSensorEventListenerOnStart() {
+ val callback = mock(AmbientLightModeMonitor.Callback::class.java)
+ ambientLightModeMonitor.start(callback)
+
+ verify(sensorManager).registerListener(any(), eq(sensor), anyInt())
+ }
+
+ @Test
+ fun shouldUnregisterSensorEventListenerOnStop() {
+ val callback = mock(AmbientLightModeMonitor.Callback::class.java)
+ ambientLightModeMonitor.start(callback)
+
+ val sensorEventListener = captureSensorEventListener()
+
+ ambientLightModeMonitor.stop()
+
+ verify(sensorManager).unregisterListener(eq(sensorEventListener))
+ }
+
+ @Test
+ fun shouldStartDebounceAlgorithmOnStart() {
+ val callback = mock(AmbientLightModeMonitor.Callback::class.java)
+ ambientLightModeMonitor.start(callback)
+
+ verify(algorithm).start(eq(callback))
+ }
+
+ @Test
+ fun shouldStopDebounceAlgorithmOnStop() {
+ val callback = mock(AmbientLightModeMonitor.Callback::class.java)
+ ambientLightModeMonitor.start(callback)
+ ambientLightModeMonitor.stop()
+
+ verify(algorithm).stop()
+ }
+
+ @Test
+ fun shouldNotRegisterForSensorUpdatesIfSensorNotAvailable() {
+ val ambientLightModeMonitor =
+ AmbientLightModeMonitor(Optional.of(algorithm), sensorManager, Optional.empty())
+
+ val callback = mock(AmbientLightModeMonitor.Callback::class.java)
+ ambientLightModeMonitor.start(callback)
+
+ verify(sensorManager, never()).registerListener(any(), any(Sensor::class.java), anyInt())
+ }
+
+ // Captures [SensorEventListener], assuming it has been registered with [sensorManager].
+ private fun captureSensorEventListener(): SensorEventListener {
+ val captor = ArgumentCaptor.forClass(SensorEventListener::class.java)
+ verify(sensorManager).registerListener(captor.capture(), any(), anyInt())
+ return captor.value
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ChargingStatusProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ChargingStatusProviderTest.java
new file mode 100644
index 000000000000..2c8c1e1e70b1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ChargingStatusProviderTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.res.Resources;
+import android.os.BatteryManager;
+import android.os.RemoteException;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.settingslib.fuelgauge.BatteryStatus;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
+
+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;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ChargingStatusProviderTest extends SysuiTestCase {
+ @Mock
+ private Resources mResources;
+ @Mock
+ private IBatteryStats mBatteryInfo;
+ @Mock
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private ChargingStatusProvider.Callback mCallback;
+
+ private ChargingStatusProvider mProvider;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ mProvider = new ChargingStatusProvider(
+ mContext, mResources, mBatteryInfo, mKeyguardUpdateMonitor);
+ }
+
+ @Test
+ public void testStartUsingReportsStatusToCallback() {
+ mProvider.startUsing(mCallback);
+ verify(mCallback).onChargingStatusChanged(false, null);
+ }
+
+ @Test
+ public void testStartUsingRegistersCallbackWithKeyguardUpdateMonitor() {
+ mProvider.startUsing(mCallback);
+ verify(mKeyguardUpdateMonitor).registerCallback(any());
+ }
+
+ @Test
+ public void testCallbackNotCalledAfterStopUsing() {
+ mProvider.startUsing(mCallback);
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ mProvider.stopUsing();
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getChargingBattery());
+ verify(mCallback, never()).onChargingStatusChanged(eq(true), any());
+ }
+
+ @Test
+ public void testKeyguardUpdateMonitorCallbackRemovedAfterStopUsing() {
+ mProvider.startUsing(mCallback);
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ mProvider.stopUsing();
+ verify(mKeyguardUpdateMonitor)
+ .removeCallback(keyguardUpdateMonitorCallbackArgumentCaptor.getValue());
+ }
+
+ @Test
+ public void testChargingStatusReportsHideWhenNotPluggedIn() {
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ mProvider.startUsing(mCallback);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getUnpluggedBattery());
+ // Once for init() and once for the status change.
+ verify(mCallback, times(2)).onChargingStatusChanged(false, null);
+ }
+
+ @Test
+ public void testChargingStatusReportsShowWhenBatteryOverheated() {
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ mProvider.startUsing(mCallback);
+ verify(mCallback).onChargingStatusChanged(false, null);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getBatteryDefender());
+ verify(mCallback).onChargingStatusChanged(eq(true), any());
+ }
+
+ @Test
+ public void testChargingStatusReportsShowWhenPluggedIn() {
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ mProvider.startUsing(mCallback);
+ verify(mCallback).onChargingStatusChanged(false, null);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getChargingBattery());
+ verify(mCallback).onChargingStatusChanged(eq(true), any());
+ }
+
+ @Test
+ public void testChargingStatusReportsChargingLimitedWhenOverheated() {
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ mProvider.startUsing(mCallback);
+ verify(mCallback).onChargingStatusChanged(false, null);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getBatteryDefender());
+ verify(mResources).getString(eq(R.string.keyguard_plugged_in_charging_limited), any());
+ }
+
+ @Test
+ public void testChargingStatusReportsChargedWhenCharged() {
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ mProvider.startUsing(mCallback);
+ verify(mCallback).onChargingStatusChanged(false, null);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getChargedBattery());
+ verify(mResources).getString(R.string.keyguard_charged);
+ }
+
+ @Test
+ public void testChargingStatusReportsPluggedInWhenDockedAndChargingTimeUnknown() throws
+ RemoteException {
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ mProvider.startUsing(mCallback);
+ verify(mCallback).onChargingStatusChanged(false, null);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ when(mBatteryInfo.computeChargeTimeRemaining()).thenReturn(-1L);
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getChargingBattery());
+ verify(mResources).getString(
+ eq(R.string.keyguard_plugged_in_dock), any());
+ }
+
+ @Test
+ public void testChargingStatusReportsTimeRemainingWhenDockedAndCharging() throws
+ RemoteException {
+ ArgumentCaptor<KeyguardUpdateMonitorCallback> keyguardUpdateMonitorCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
+ mProvider.startUsing(mCallback);
+ verify(mCallback).onChargingStatusChanged(false, null);
+ verify(mKeyguardUpdateMonitor)
+ .registerCallback(keyguardUpdateMonitorCallbackArgumentCaptor.capture());
+ when(mBatteryInfo.computeChargeTimeRemaining()).thenReturn(1L);
+ keyguardUpdateMonitorCallbackArgumentCaptor.getValue()
+ .onRefreshBatteryInfo(getChargingBattery());
+ verify(mResources).getString(
+ eq(R.string.keyguard_indication_charging_time_dock), any(), any());
+ }
+
+ private BatteryStatus getUnpluggedBattery() {
+ return new BatteryStatus(BatteryManager.BATTERY_STATUS_NOT_CHARGING,
+ 80, BatteryManager.BATTERY_PLUGGED_ANY, BatteryManager.BATTERY_HEALTH_GOOD,
+ 0, true);
+ }
+
+ private BatteryStatus getChargingBattery() {
+ return new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
+ 80, BatteryManager.BATTERY_PLUGGED_DOCK,
+ BatteryManager.BATTERY_HEALTH_GOOD, 0, true);
+ }
+
+ private BatteryStatus getChargedBattery() {
+ return new BatteryStatus(BatteryManager.BATTERY_STATUS_FULL,
+ 100, BatteryManager.BATTERY_PLUGGED_DOCK,
+ BatteryManager.BATTERY_HEALTH_GOOD, 0, true);
+ }
+
+ private BatteryStatus getBatteryDefender() {
+ return new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
+ 80, BatteryManager.BATTERY_PLUGGED_DOCK,
+ BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE, 0, true);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/DirectBootConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/DirectBootConditionTest.kt
new file mode 100644
index 000000000000..173f243cb2b0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/DirectBootConditionTest.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock
+
+import android.content.Intent
+import android.os.UserManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.shared.condition.Condition
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+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.MockitoAnnotations
+
+@SmallTest
+@OptIn(ExperimentalCoroutinesApi::class)
+class DirectBootConditionTest : SysuiTestCase() {
+ @Mock private lateinit var userManager: UserManager
+ @Mock private lateinit var callback: Condition.Callback
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun receiverRegisteredOnStart() = runTest {
+ val condition = buildCondition(this)
+ // No receivers are registered yet
+ assertThat(fakeBroadcastDispatcher.numReceiversRegistered).isEqualTo(0)
+ condition.addCallback(callback)
+ advanceUntilIdle()
+ // Receiver is registered after a callback is added
+ assertThat(fakeBroadcastDispatcher.numReceiversRegistered).isEqualTo(1)
+ condition.removeCallback(callback)
+ }
+
+ @Test
+ fun unregisterReceiverOnStop() = runTest {
+ val condition = buildCondition(this)
+
+ condition.addCallback(callback)
+ advanceUntilIdle()
+
+ assertThat(fakeBroadcastDispatcher.numReceiversRegistered).isEqualTo(1)
+
+ condition.removeCallback(callback)
+ advanceUntilIdle()
+
+ // Receiver is unregistered when nothing is listening to the condition
+ assertThat(fakeBroadcastDispatcher.numReceiversRegistered).isEqualTo(0)
+ }
+
+ @Test
+ fun callbackTriggeredWhenUserUnlocked() = runTest {
+ val condition = buildCondition(this)
+
+ setUserUnlocked(false)
+ condition.addCallback(callback)
+ advanceUntilIdle()
+
+ assertThat(condition.isConditionMet).isTrue()
+
+ setUserUnlocked(true)
+ advanceUntilIdle()
+
+ assertThat(condition.isConditionMet).isFalse()
+ condition.removeCallback(callback)
+ }
+
+ private fun buildCondition(scope: CoroutineScope): DirectBootCondition {
+ return DirectBootCondition(fakeBroadcastDispatcher, userManager, scope)
+ }
+
+ private fun setUserUnlocked(unlocked: Boolean) {
+ whenever(userManager.isUserUnlocked).thenReturn(unlocked)
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_USER_UNLOCKED),
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ForceLowLightConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ForceLowLightConditionTest.java
new file mode 100644
index 000000000000..7297e0f3bff5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ForceLowLightConditionTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.statusbar.commandline.Command;
+import com.android.systemui.statusbar.commandline.CommandRegistry;
+
+import kotlin.jvm.functions.Function0;
+
+import kotlinx.coroutines.CoroutineScope;
+
+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.io.PrintWriter;
+import java.util.Arrays;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ForceLowLightConditionTest extends SysuiTestCase {
+ @Mock
+ private CommandRegistry mCommandRegistry;
+
+ @Mock
+ private Condition.Callback mCallback;
+
+ @Mock
+ private PrintWriter mPrintWriter;
+
+ @Mock
+ CoroutineScope mScope;
+
+ private ForceLowLightCondition mCondition;
+ private Command mCommand;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mCondition = new ForceLowLightCondition(mScope, mCommandRegistry);
+ mCondition.addCallback(mCallback);
+ ArgumentCaptor<Function0<Command>> commandCaptor =
+ ArgumentCaptor.forClass(Function0.class);
+ verify(mCommandRegistry).registerCommand(eq(ForceLowLightCondition.COMMAND_ROOT),
+ commandCaptor.capture());
+ mCommand = commandCaptor.getValue().invoke();
+ }
+
+ @Test
+ public void testEnableLowLight() {
+ mCommand.execute(mPrintWriter,
+ Arrays.asList(ForceLowLightCondition.COMMAND_ENABLE_LOW_LIGHT));
+ verify(mCallback).onConditionChanged(mCondition);
+ assertThat(mCondition.isConditionSet()).isTrue();
+ assertThat(mCondition.isConditionMet()).isTrue();
+ }
+
+ @Test
+ public void testDisableLowLight() {
+ mCommand.execute(mPrintWriter,
+ Arrays.asList(ForceLowLightCondition.COMMAND_DISABLE_LOW_LIGHT));
+ verify(mCallback).onConditionChanged(mCondition);
+ assertThat(mCondition.isConditionSet()).isTrue();
+ assertThat(mCondition.isConditionMet()).isFalse();
+ }
+
+ @Test
+ public void testClearEnableLowLight() {
+ mCommand.execute(mPrintWriter,
+ Arrays.asList(ForceLowLightCondition.COMMAND_ENABLE_LOW_LIGHT));
+ verify(mCallback).onConditionChanged(mCondition);
+ assertThat(mCondition.isConditionSet()).isTrue();
+ assertThat(mCondition.isConditionMet()).isTrue();
+ Mockito.clearInvocations(mCallback);
+ mCommand.execute(mPrintWriter,
+ Arrays.asList(ForceLowLightCondition.COMMAND_CLEAR_LOW_LIGHT));
+ verify(mCallback).onConditionChanged(mCondition);
+ assertThat(mCondition.isConditionSet()).isFalse();
+ assertThat(mCondition.isConditionMet()).isFalse();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockAnimationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockAnimationProviderTest.kt
new file mode 100644
index 000000000000..663880f098cd
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockAnimationProviderTest.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock
+
+import android.animation.Animator
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+class LowLightClockAnimationProviderTest : SysuiTestCase() {
+
+ private val underTest by lazy {
+ LowLightClockAnimationProvider(
+ Y_TRANSLATION_ANIMATION_OFFSET,
+ Y_TRANSLATION_ANIMATION_DURATION_MILLIS,
+ ALPHA_ANIMATION_IN_START_DELAY_MILLIS,
+ ALPHA_ANIMATION_DURATION_MILLIS,
+ )
+ }
+
+ @Test
+ fun animationOutEndsImmediatelyIfViewIsNull() {
+ val animator = underTest.provideAnimationOut(null, null)
+
+ val listener = mock<Animator.AnimatorListener>()
+ animator.addListener(listener)
+
+ animator.start()
+ verify(listener).onAnimationStart(any(), eq(false))
+ verify(listener).onAnimationEnd(any(), eq(false))
+ }
+
+ @Test
+ fun animationInEndsImmediatelyIfViewIsNull() {
+ val animator = underTest.provideAnimationIn(null, null)
+
+ val listener = mock<Animator.AnimatorListener>()
+ animator.addListener(listener)
+
+ animator.start()
+ verify(listener).onAnimationStart(any(), eq(false))
+ verify(listener).onAnimationEnd(any(), eq(false))
+ }
+
+ private companion object {
+ const val Y_TRANSLATION_ANIMATION_OFFSET = 100
+ const val Y_TRANSLATION_ANIMATION_DURATION_MILLIS = 100L
+ const val ALPHA_ANIMATION_IN_START_DELAY_MILLIS = 200L
+ const val ALPHA_ANIMATION_DURATION_MILLIS = 300L
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockDreamServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockDreamServiceTest.java
new file mode 100644
index 000000000000..22a13cc41425
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightClockDreamServiceTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.animation.Animator;
+import android.os.RemoteException;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.dream.lowlight.LowLightTransitionCoordinator;
+import com.android.systemui.SysuiTestCase;
+
+import com.google.android.systemui.lowlightclock.LowLightClockDreamService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class LowLightClockDreamServiceTest extends SysuiTestCase {
+ @Mock
+ private ChargingStatusProvider mChargingStatusProvider;
+ @Mock
+ private LowLightDisplayController mDisplayController;
+ @Mock
+ private LowLightClockAnimationProvider mAnimationProvider;
+ @Mock
+ private LowLightTransitionCoordinator mLowLightTransitionCoordinator;
+ @Mock
+ Animator mAnimationInAnimator;
+ @Mock
+ Animator mAnimationOutAnimator;
+
+ private LowLightClockDreamService mService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mService = new LowLightClockDreamService(
+ mChargingStatusProvider,
+ mAnimationProvider,
+ mLowLightTransitionCoordinator,
+ Optional.of(() -> mDisplayController));
+
+ when(mAnimationProvider.provideAnimationIn(any(), any())).thenReturn(mAnimationInAnimator);
+ when(mAnimationProvider.provideAnimationOut(any())).thenReturn(
+ mAnimationOutAnimator);
+ }
+
+ @Test
+ public void testSetDbmStateWhenSupported() throws RemoteException {
+ when(mDisplayController.isDisplayBrightnessModeSupported()).thenReturn(true);
+
+ mService.onDreamingStarted();
+
+ verify(mDisplayController).setDisplayBrightnessModeEnabled(true);
+ }
+
+ @Test
+ public void testNotSetDbmStateWhenNotSupported() throws RemoteException {
+ when(mDisplayController.isDisplayBrightnessModeSupported()).thenReturn(false);
+
+ mService.onDreamingStarted();
+
+ verify(mDisplayController, never()).setDisplayBrightnessModeEnabled(anyBoolean());
+ }
+
+ @Test
+ public void testClearDbmState() throws RemoteException {
+ when(mDisplayController.isDisplayBrightnessModeSupported()).thenReturn(true);
+
+ mService.onDreamingStarted();
+ clearInvocations(mDisplayController);
+
+ mService.onDreamingStopped();
+
+ verify(mDisplayController).setDisplayBrightnessModeEnabled(false);
+ }
+
+ @Test
+ public void testAnimationsStartedOnDreamingStarted() {
+ mService.onDreamingStarted();
+
+ // Entry animation started.
+ verify(mAnimationInAnimator).start();
+ }
+
+ @Test
+ public void testAnimationsStartedOnWakeUp() {
+ // Start dreaming then wake up.
+ mService.onDreamingStarted();
+ mService.onWakeUp();
+
+ // Entry animation started.
+ verify(mAnimationInAnimator).cancel();
+
+ // Exit animation started.
+ verify(mAnimationOutAnimator).start();
+ }
+
+ @Test
+ public void testAnimationsStartedBeforeExitingLowLight() {
+ mService.onBeforeExitLowLight();
+
+ // Exit animation started.
+ verify(mAnimationOutAnimator).start();
+ }
+
+ @Test
+ public void testWakeUpAnimationCancelledOnDetach() {
+ mService.onWakeUp();
+
+ // Exit animation started.
+ verify(mAnimationOutAnimator).start();
+
+ mService.onDetachedFromWindow();
+
+ verify(mAnimationOutAnimator).cancel();
+ }
+
+ @Test
+ public void testExitLowLightAnimationCancelledOnDetach() {
+ mService.onBeforeExitLowLight();
+
+ // Exit animation started.
+ verify(mAnimationOutAnimator).start();
+
+ mService.onDetachedFromWindow();
+
+ verify(mAnimationOutAnimator).cancel();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightConditionTest.java
new file mode 100644
index 000000000000..2c216244985e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightConditionTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.SysuiTestCase;
+
+import kotlinx.coroutines.CoroutineScope;
+
+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;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class LowLightConditionTest extends SysuiTestCase {
+ @Mock
+ private AmbientLightModeMonitor mAmbientLightModeMonitor;
+ @Mock
+ private UiEventLogger mUiEventLogger;
+ @Mock
+ CoroutineScope mScope;
+ private LowLightCondition mCondition;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mCondition = new LowLightCondition(mScope, mAmbientLightModeMonitor, mUiEventLogger);
+ mCondition.start();
+ }
+
+ @Test
+ public void testLowLightFalse() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
+ assertThat(mCondition.isConditionMet()).isFalse();
+ }
+
+ @Test
+ public void testLowLightTrue() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ assertThat(mCondition.isConditionMet()).isTrue();
+ }
+
+ @Test
+ public void testUndecidedLowLightStateIgnored() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ assertThat(mCondition.isConditionMet()).isTrue();
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_UNDECIDED);
+ assertThat(mCondition.isConditionMet()).isTrue();
+ }
+
+ @Test
+ public void testLowLightChange() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
+ assertThat(mCondition.isConditionMet()).isFalse();
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ assertThat(mCondition.isConditionMet()).isTrue();
+ }
+
+ @Test
+ public void testResetIsConditionMetUponStop() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ assertThat(mCondition.isConditionMet()).isTrue();
+
+ mCondition.stop();
+ assertThat(mCondition.isConditionMet()).isFalse();
+ }
+
+ @Test
+ public void testLoggingAmbientLightNotLowToLow() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ // Only logged once.
+ verify(mUiEventLogger, times(1)).log(any());
+ // Logged with the correct state.
+ verify(mUiEventLogger).log(LowLightDockEvent.AMBIENT_LIGHT_TO_DARK);
+ }
+
+ @Test
+ public void testLoggingAmbientLightLowToLow() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ reset(mUiEventLogger);
+
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ // Doesn't log.
+ verify(mUiEventLogger, never()).log(any());
+ }
+
+ @Test
+ public void testLoggingAmbientLightNotLowToNotLow() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
+ // Doesn't log.
+ verify(mUiEventLogger, never()).log(any());
+ }
+
+ @Test
+ public void testLoggingAmbientLightLowToNotLow() {
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_DARK);
+ reset(mUiEventLogger);
+
+ changeLowLightMode(AmbientLightModeMonitor.AMBIENT_LIGHT_MODE_LIGHT);
+ // Only logged once.
+ verify(mUiEventLogger).log(any());
+ // Logged with the correct state.
+ verify(mUiEventLogger).log(LowLightDockEvent.AMBIENT_LIGHT_TO_LIGHT);
+ }
+
+ private void changeLowLightMode(int mode) {
+ ArgumentCaptor<AmbientLightModeMonitor.Callback> ambientLightCallbackCaptor =
+ ArgumentCaptor.forClass(AmbientLightModeMonitor.Callback.class);
+ verify(mAmbientLightModeMonitor).start(ambientLightCallbackCaptor.capture());
+ ambientLightCallbackCaptor.getValue().onChange(mode);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightMonitorTest.java
new file mode 100644
index 000000000000..69485e848a6a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/LowLightMonitorTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_LOW_LIGHT;
+import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_REGULAR;
+import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.dream.lowlight.LowLightDreamManager;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.shared.condition.Monitor;
+
+import dagger.Lazy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Set;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class LowLightMonitorTest extends SysuiTestCase {
+
+ @Mock
+ private Lazy<LowLightDreamManager> mLowLightDreamManagerLazy;
+ @Mock
+ private LowLightDreamManager mLowLightDreamManager;
+ @Mock
+ private Monitor mMonitor;
+ @Mock
+ private ScreenLifecycle mScreenLifecycle;
+ @Mock
+ private LowLightLogger mLogger;
+
+ private LowLightMonitor mLowLightMonitor;
+
+ @Mock
+ Lazy<Set<Condition>> mLazyConditions;
+
+ @Mock
+ private PackageManager mPackageManager;
+
+ @Mock
+ private ComponentName mDreamComponent;
+
+ Condition mCondition = mock(Condition.class);
+ Set<Condition> mConditionSet = Set.of(mCondition);
+
+ @Captor
+ ArgumentCaptor<Monitor.Subscription> mPreconditionsSubscriptionCaptor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mLowLightDreamManagerLazy.get()).thenReturn(mLowLightDreamManager);
+ when(mLazyConditions.get()).thenReturn(mConditionSet);
+ mLowLightMonitor = new LowLightMonitor(mLowLightDreamManagerLazy,
+ mMonitor, mLazyConditions, mScreenLifecycle, mLogger, mDreamComponent,
+ mPackageManager);
+ }
+
+ @Test
+ public void testSetAmbientLowLightWhenInLowLight() {
+ mLowLightMonitor.onConditionsChanged(true);
+ // Verify setting low light when condition is true
+ verify(mLowLightDreamManager).setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+ }
+
+ @Test
+ public void testExitAmbientLowLightWhenNotInLowLight() {
+ mLowLightMonitor.onConditionsChanged(true);
+ mLowLightMonitor.onConditionsChanged(false);
+ // Verify ambient light toggles back to light mode regular
+ verify(mLowLightDreamManager).setAmbientLightMode(AMBIENT_LIGHT_MODE_REGULAR);
+ }
+
+ @Test
+ public void testStartMonitorLowLightConditionsWhenScreenTurnsOn() {
+ mLowLightMonitor.onScreenTurnedOn();
+
+ // Verify subscribing to low light conditions monitor when screen turns on.
+ verify(mMonitor).addSubscription(any());
+ }
+
+ @Test
+ public void testStopMonitorLowLightConditionsWhenScreenTurnsOff() {
+ final Monitor.Subscription.Token token = mock(Monitor.Subscription.Token.class);
+ when(mMonitor.addSubscription(any())).thenReturn(token);
+ mLowLightMonitor.onScreenTurnedOn();
+
+ // Verify removing subscription when screen turns off.
+ mLowLightMonitor.onScreenTurnedOff();
+ verify(mMonitor).removeSubscription(token);
+ }
+
+ @Test
+ public void testSubscribeToLowLightConditionsOnlyOnceWhenScreenTurnsOn() {
+ final Monitor.Subscription.Token token = mock(Monitor.Subscription.Token.class);
+ when(mMonitor.addSubscription(any())).thenReturn(token);
+
+ mLowLightMonitor.onScreenTurnedOn();
+ mLowLightMonitor.onScreenTurnedOn();
+ // Verify subscription is only added once.
+ verify(mMonitor, times(1)).addSubscription(any());
+ }
+
+ @Test
+ public void testSubscribedToExpectedConditions() {
+ final Monitor.Subscription.Token token = mock(Monitor.Subscription.Token.class);
+ when(mMonitor.addSubscription(any())).thenReturn(token);
+
+ mLowLightMonitor.onScreenTurnedOn();
+ mLowLightMonitor.onScreenTurnedOn();
+ Set<Condition> conditions = captureConditions();
+ // Verify Monitor is subscribed to the expected conditions
+ assertThat(conditions).isEqualTo(mConditionSet);
+ }
+
+ @Test
+ public void testNotUnsubscribeIfNotSubscribedWhenScreenTurnsOff() {
+ mLowLightMonitor.onScreenTurnedOff();
+
+ // Verify doesn't remove subscription since there is none.
+ verify(mMonitor, never()).removeSubscription(any());
+ }
+
+ @Test
+ public void testSubscribeIfScreenIsOnWhenStarting() {
+ when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_ON);
+ mLowLightMonitor.start();
+ // Verify to add subscription on start if the screen state is on
+ verify(mMonitor, times(1)).addSubscription(any());
+ }
+
+ @Test
+ public void testNoSubscribeIfDreamNotPresent() {
+ LowLightMonitor lowLightMonitor = new LowLightMonitor(mLowLightDreamManagerLazy,
+ mMonitor, mLazyConditions, mScreenLifecycle, mLogger, null, mPackageManager);
+ when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_ON);
+ lowLightMonitor.start();
+ verify(mScreenLifecycle, never()).addObserver(any());
+ }
+
+ private Set<Condition> captureConditions() {
+ verify(mMonitor).addSubscription(mPreconditionsSubscriptionCaptor.capture());
+ return mPreconditionsSubscriptionCaptor.getValue().getConditions();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ScreenSaverEnabledConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ScreenSaverEnabledConditionTest.java
new file mode 100644
index 000000000000..366c071fb93f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/lowlightclock/ScreenSaverEnabledConditionTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.lowlightclock;
+
+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.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
+
+import kotlinx.coroutines.CoroutineScope;
+
+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 ScreenSaverEnabledConditionTest extends SysuiTestCase {
+ @Mock
+ private Resources mResources;
+ @Mock
+ private SecureSettings mSecureSettings;
+ @Mock
+ CoroutineScope mScope;
+ @Captor
+ private ArgumentCaptor<ContentObserver> mSettingsObserverCaptor;
+ private ScreenSaverEnabledCondition mCondition;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ // Default dreams to enabled by default
+ doReturn(true).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_dreamsEnabledByDefault);
+
+ mCondition = new ScreenSaverEnabledCondition(mScope, mResources, mSecureSettings);
+ }
+
+ @Test
+ public void testScreenSaverInitiallyEnabled() {
+ setScreenSaverEnabled(true);
+ mCondition.start();
+ assertThat(mCondition.isConditionMet()).isTrue();
+ }
+
+ @Test
+ public void testScreenSaverInitiallyDisabled() {
+ setScreenSaverEnabled(false);
+ mCondition.start();
+ assertThat(mCondition.isConditionMet()).isFalse();
+ }
+
+ @Test
+ public void testScreenSaverStateChanges() {
+ setScreenSaverEnabled(false);
+ mCondition.start();
+ assertThat(mCondition.isConditionMet()).isFalse();
+
+ setScreenSaverEnabled(true);
+ final ContentObserver observer = captureSettingsObserver();
+ observer.onChange(/* selfChange= */ false);
+ assertThat(mCondition.isConditionMet()).isTrue();
+ }
+
+ private void setScreenSaverEnabled(boolean enabled) {
+ when(mSecureSettings.getIntForUser(eq(Settings.Secure.SCREENSAVER_ENABLED), anyInt(),
+ eq(UserHandle.USER_CURRENT))).thenReturn(enabled ? 1 : 0);
+ }
+
+ private ContentObserver captureSettingsObserver() {
+ verify(mSecureSettings).registerContentObserverForUserSync(
+ eq(Settings.Secure.SCREENSAVER_ENABLED),
+ mSettingsObserverCaptor.capture(), eq(UserHandle.USER_CURRENT));
+ return mSettingsObserverCaptor.getValue();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImplTest.kt
index e2a2b7a91319..38dc03e9b5ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImplTest.kt
@@ -41,7 +41,6 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.anyLong
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
@@ -90,7 +89,6 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
fun setup() {
MockitoAnnotations.initMocks(this)
MediaPlayerData.clear()
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
mediaDataFilter =
LegacyMediaDataFilterImpl(
context,
@@ -100,7 +98,7 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
executor,
clock,
logger,
- mediaFlags
+ mediaFlags,
)
mediaDataFilter.mediaDataManager = mediaDataManager
mediaDataFilter.addListener(listener)
@@ -114,7 +112,7 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
userId = USER_MAIN,
packageName = PACKAGE,
instanceId = INSTANCE_ID,
- appUid = APP_UID
+ appUid = APP_UID,
)
dataGuest = dataMain.copy(userId = USER_GUEST)
dataPrivateProfile = dataMain.copy(userId = PRIVATE_PROFILE)
@@ -476,7 +474,7 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
// Smartspace update shouldn't be propagated for the empty rec list.
@@ -505,7 +503,7 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
// Smartspace update should also be propagated but not prioritized.
@@ -542,7 +540,7 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
@@ -553,61 +551,6 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
}
@Test
- fun testOnSmartspaceLoaded_persistentEnabled_isInactive_notifiesListeners() {
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- whenever(smartspaceData.isActive).thenReturn(false)
-
- mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
- assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
- assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isTrue()
- }
-
- @Test
- fun testOnSmartspaceLoaded_persistentEnabled_inactive_hasRecentMedia_staysInactive() {
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- whenever(smartspaceData.isActive).thenReturn(false)
-
- // If there is media that was recently played but inactive
- 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 an inactive recommendation is loaded
- mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-
- // Smartspace is loaded but the media stays inactive
- verify(listener)
- .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
- verify(listener, never())
- .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean())
- assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
- assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isTrue()
- }
-
- @Test
- fun testOnSwipeToDismiss_persistentEnabled_recommendationSetInactive() {
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
-
- val data =
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(
- targetId = SMARTSPACE_KEY,
- isActive = true,
- packageName = SMARTSPACE_PACKAGE,
- recommendations = listOf(smartspaceMediaRecommendationItem),
- )
- mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, data)
- mediaDataFilter.onSwipeToDismiss()
-
- verify(mediaDataManager).setRecommendationInactive(eq(SMARTSPACE_KEY))
- 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())
@@ -629,7 +572,7 @@ class LegacyMediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
// And send the smartspace data, but not prioritized
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
index 2815b97691ad..676d8fa06d82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
@@ -54,7 +54,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.Flags.MEDIA_REMOTE_RESUME
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
-import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testDispatcher
@@ -236,6 +235,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
modifyNotification(context).also {
it.setSmallIcon(android.R.drawable.ic_media_pause)
it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+ it.setContentIntent(getNewPendingIntent())
}
build()
}
@@ -293,7 +293,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, false)
whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
}
@@ -2158,6 +2157,28 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
}
+ @Test
+ @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+ fun postDifferentIntentNotifications_CallsListeners() {
+ addNotificationAndLoad()
+ reset(listener)
+ mediaNotification =
+ mediaNotification.also { it.notification.contentIntent = getNewPendingIntent() }
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+
+ testScope.assertRunAllReady(foreground = 1, background = 1)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false),
+ )
+ verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
+ }
+
private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) {
runCurrent()
if (Flags.mediaLoadMetadataViaMediaDataLoader()) {
@@ -2237,4 +2258,14 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
backgroundExecutor.runAllReady()
foregroundExecutor.runAllReady()
}
+
+ private fun getNewPendingIntent(): PendingIntent {
+ val intent = Intent().setAction(null)
+ return PendingIntent.getBroadcast(
+ mContext,
+ 1,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE,
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
index 3705909cbc2b..811d2e2b2b06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
@@ -20,7 +20,6 @@ import android.R
import android.app.smartspace.SmartspaceAction
import android.graphics.drawable.Icon
import android.os.Bundle
-import android.os.Process
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -42,7 +41,6 @@ import com.android.systemui.media.controls.ui.controller.MediaPlayerData
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaSmartspaceLogger
import com.android.systemui.media.controls.util.MediaUiEventLogger
-import com.android.systemui.media.controls.util.SmallHash
import com.android.systemui.media.controls.util.mediaSmartspaceLogger
import com.android.systemui.media.controls.util.mockMediaSmartspaceLogger
import com.android.systemui.settings.UserTracker
@@ -60,7 +58,6 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.never
@@ -121,7 +118,6 @@ class MediaDataFilterImplTest : SysuiTestCase() {
fun setup() {
MockitoAnnotations.initMocks(this)
MediaPlayerData.clear()
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
testScope = TestScope()
mediaDataFilter =
MediaDataFilterImpl(
@@ -148,7 +144,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
userId = USER_MAIN,
packageName = PACKAGE,
instanceId = INSTANCE_ID,
- appUid = APP_UID
+ appUid = APP_UID,
)
dataGuest = dataMain.copy(userId = USER_GUEST, instanceId = INSTANCE_ID_GUEST)
dataPrivateProfile = dataMain.copy(userId = PRIVATE_PROFILE, instanceId = INSTANCE_ID_GUEST)
@@ -302,7 +298,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
eq(dataMain),
anyBoolean(),
anyInt(),
- anyBoolean()
+ anyBoolean(),
)
verify(mediaLogger, never())
.logMediaLoaded(eq(dataMain.instanceId), anyBoolean(), anyString())
@@ -406,7 +402,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -425,7 +421,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isTrue()
@@ -444,7 +440,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -463,7 +459,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -483,7 +479,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isTrue()
@@ -513,7 +509,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -524,7 +520,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -561,7 +557,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
anyInt(),
anyInt(),
anyInt(),
- eq(true)
+ eq(true),
)
verify(mediaDataProcessor).setInactive(eq(KEY), eq(true), eq(true))
}
@@ -584,7 +580,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isTrue()
@@ -613,7 +609,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -641,7 +637,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
val controlCommonModel =
MediaCommonModel.MediaControl(
MediaDataLoadingModel.Loaded(dataMain.instanceId),
- true
+ true,
)
val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
mediaDataFilter.onMediaDataLoaded(KEY, null, dataOld)
@@ -653,7 +649,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isTrue()
@@ -689,7 +685,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -715,7 +711,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
val controlCommonModel =
MediaCommonModel.MediaControl(
MediaDataLoadingModel.Loaded(dataMain.instanceId),
- true
+ true,
)
mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
repository.setOrderedMedia()
@@ -737,7 +733,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -784,7 +780,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
controlCommonModel.copy(
mediaLoadingModel.copy(
receivedSmartspaceCardLatency = 100,
- isSsReactivated = true
+ isSsReactivated = true,
)
)
assertThat(currentMedia).containsExactly(controlCommonModel)
@@ -792,7 +788,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isTrue()
@@ -803,13 +799,13 @@ class MediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
verify(mediaLogger)
.logMediaLoaded(
eq(dataCurrentAndActive.instanceId),
eq(dataCurrentAndActive.active),
- anyString()
+ anyString(),
)
// Smartspace update shouldn't be propagated for the empty rec list.
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
@@ -857,19 +853,19 @@ class MediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
verify(mediaLogger)
.logMediaLoaded(
eq(dataCurrentAndActive.instanceId),
eq(dataCurrentAndActive.active),
- anyString()
+ anyString(),
)
assertThat(
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isTrue()
@@ -878,7 +874,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
controlCommonModel.copy(
mediaLoadingModel.copy(
receivedSmartspaceCardLatency = 100,
- isSsReactivated = true
+ isSsReactivated = true,
)
)
assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel)
@@ -907,7 +903,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -924,7 +920,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
val controlCommonModel =
MediaCommonModel.MediaControl(
MediaDataLoadingModel.Loaded(dataMain.instanceId),
- true
+ true,
)
val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
@@ -948,13 +944,13 @@ class MediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
verify(mediaLogger)
.logMediaLoaded(
eq(dataCurrentAndActive.instanceId),
eq(dataCurrentAndActive.active),
- anyString()
+ anyString(),
)
mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
@@ -966,7 +962,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isFalse()
@@ -974,129 +970,6 @@ class MediaDataFilterImplTest : SysuiTestCase() {
}
@Test
- fun onSmartspaceLoaded_persistentEnabled_isInactive() =
- testScope.runTest {
- val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
- val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
- val reactivatedKey by collectLastValue(repository.reactivatedId)
- val currentMedia by collectLastValue(repository.currentMedia)
- val recsCommonModel =
- MediaCommonModel.MediaRecommendations(
- SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
- )
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- whenever(smartspaceData.isActive).thenReturn(false)
-
- mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-
- verify(listener)
- .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
- verify(mediaLogger).logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(false), anyString())
- assertThat(currentMedia).containsExactly(recsCommonModel)
- assertThat(
- hasActiveMediaOrRecommendation(
- selectedUserEntries,
- smartspaceMediaData,
- reactivatedKey
- )
- )
- .isFalse()
- assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData))
- .isTrue()
- }
-
- @Test
- fun onSmartspaceLoaded_persistentEnabled_inactive_hasRecentMedia_staysInactive() =
- testScope.runTest {
- val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
- val smartspaceMediaData by collectLastValue(repository.smartspaceMediaData)
- val reactivatedKey by collectLastValue(repository.reactivatedId)
- val currentMedia by collectLastValue(repository.currentMedia)
- val recsCommonModel =
- MediaCommonModel.MediaRecommendations(
- SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY)
- )
- val controlCommonModel =
- MediaCommonModel.MediaControl(
- MediaDataLoadingModel.Loaded(dataMain.instanceId),
- true
- )
-
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
- whenever(smartspaceData.isActive).thenReturn(false)
-
- // If there is media that was recently played but inactive
- val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
- mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
- repository.setOrderedMedia()
-
- verify(listener)
- .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
- verify(mediaLogger)
- .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString())
- assertThat(currentMedia).containsExactly(controlCommonModel)
-
- reset(mediaLogger)
-
- // And an inactive recommendation is loaded
- mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
-
- // Smartspace is loaded but the media stays inactive
- verify(listener)
- .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
- verify(mediaLogger).logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(false), anyString())
- verify(listener, never())
- .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean())
- verify(mediaLogger, never()).logMediaLoaded(any(), anyBoolean(), anyString())
- assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel)
- assertThat(
- hasActiveMediaOrRecommendation(
- selectedUserEntries,
- smartspaceMediaData,
- reactivatedKey
- )
- )
- .isFalse()
- assertThat(hasAnyMediaOrRecommendation(selectedUserEntries, smartspaceMediaData))
- .isTrue()
- }
-
- @Test
- fun onSwipeToDismiss_persistentEnabled_recommendationSetInactive() {
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
-
- val data =
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(
- targetId = SMARTSPACE_KEY,
- isActive = true,
- packageName = SMARTSPACE_PACKAGE,
- recommendations =
- listOf(
- smartspaceMediaRecommendationItem,
- smartspaceMediaRecommendationItem,
- smartspaceMediaRecommendationItem
- ),
- )
- mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, data)
-
- mediaDataFilter.onSwipeToDismiss(1)
-
- verify(smartspaceLogger)
- .logSmartspaceCardUIEvent(
- MediaSmartspaceLogger.SMARTSPACE_CARD_DISMISS_EVENT,
- SmallHash.hash(data.targetId),
- Process.INVALID_UID,
- surface = 1,
- cardinality = 1,
- isRecommendationCard = true,
- isSwipeToDismiss = true
- )
- verify(mediaDataProcessor).setRecommendationInactive(eq(SMARTSPACE_KEY))
- verify(mediaDataProcessor, never())
- .dismissSmartspaceRecommendation(eq(SMARTSPACE_KEY), anyLong())
- }
-
- @Test
fun smartspaceLoaded_shouldTriggerResume_doesTrigger() =
testScope.runTest {
val selectedUserEntries by collectLastValue(repository.selectedUserEntries)
@@ -1133,7 +1006,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
controlCommonModel.copy(
mediaLoadingModel.copy(
receivedSmartspaceCardLatency = 100,
- isSsReactivated = true
+ isSsReactivated = true,
)
)
verify(listener)
@@ -1143,20 +1016,20 @@ class MediaDataFilterImplTest : SysuiTestCase() {
eq(dataCurrentAndActive),
eq(true),
eq(100),
- eq(true)
+ eq(true),
)
verify(mediaLogger)
.logMediaLoaded(
eq(dataCurrentAndActive.instanceId),
eq(dataCurrentAndActive.active),
- anyString()
+ anyString(),
)
assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel)
assertThat(
hasActiveMediaOrRecommendation(
selectedUserEntries,
smartspaceMediaData,
- reactivatedKey
+ reactivatedKey,
)
)
.isTrue()
@@ -1177,7 +1050,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
val controlCommonModel =
MediaCommonModel.MediaControl(
MediaDataLoadingModel.Loaded(dataMain.instanceId),
- true
+ true,
)
// WHEN we have media that was recently played, but not currently active
@@ -1213,7 +1086,7 @@ class MediaDataFilterImplTest : SysuiTestCase() {
private fun hasActiveMediaOrRecommendation(
entries: Map<InstanceId, MediaData>?,
smartspaceMediaData: SmartspaceMediaData?,
- reactivatedId: InstanceId?
+ reactivatedId: InstanceId?,
): Boolean {
if (entries == null || smartspaceMediaData == null) {
return false
@@ -1229,17 +1102,13 @@ class MediaDataFilterImplTest : SysuiTestCase() {
private fun hasAnyMediaOrRecommendation(
entries: Map<InstanceId, MediaData>?,
- smartspaceMediaData: SmartspaceMediaData?
+ smartspaceMediaData: SmartspaceMediaData?,
): Boolean {
if (entries == null || smartspaceMediaData == null) {
return false
}
return entries.isNotEmpty() ||
- (if (mediaFlags.isPersistentSsCardEnabled()) {
- smartspaceMediaData.isValid()
- } else {
- smartspaceMediaData.isActive && smartspaceMediaData.isValid()
- })
+ (smartspaceMediaData.isActive && smartspaceMediaData.isValid())
}
private fun hasAnyMedia(entries: Map<InstanceId, MediaData>?): Boolean {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index b9ebce816c5c..496b31990b9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -57,7 +57,6 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags.MEDIA_REMOTE_RESUME
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
-import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testDispatcher
@@ -252,6 +251,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
verify(mediaTimeoutListener).stateCallback = capture(stateCallbackCaptor)
verify(mediaTimeoutListener).sessionCallback = capture(sessionCallbackCaptor)
session = MediaSession(context, "MediaDataProcessorTestSession")
+
mediaNotification =
SbnBuilder().run {
setUser(UserHandle(USER_ID))
@@ -259,6 +259,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
modifyNotification(context).also {
it.setSmallIcon(android.R.drawable.ic_media_pause)
it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+ it.setContentIntent(getNewPendingIntent())
}
build()
}
@@ -316,7 +317,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
- fakeFeatureFlags.set(MEDIA_RETAIN_RECOMMENDATIONS, false)
whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
}
@@ -1524,7 +1524,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
}
@Test
- @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
+ @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX)
fun postWithPlaybackActions_drawablesReused() {
whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
@@ -1557,7 +1557,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
}
@Test
- @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
+ @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX)
fun postWithPlaybackActions_drawablesNotReused() {
whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
@@ -2252,6 +2252,33 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
}
+ @Test
+ @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+ fun postDifferentIntentNotifications_CallsListeners() {
+ whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+ whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+
+ mediaDataProcessor.addInternalListener(mediaDataFilter)
+ mediaDataFilter.mediaDataProcessor = mediaDataProcessor
+ addNotificationAndLoad()
+ reset(listener)
+ mediaNotification =
+ mediaNotification.also { it.notification.contentIntent = getNewPendingIntent() }
+ mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
+
+ testScope.assertRunAllReady(foreground = 1, background = 1)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false),
+ )
+ verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
+ }
+
private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) {
runCurrent()
if (Flags.mediaLoadMetadataViaMediaDataLoader()) {
@@ -2331,4 +2358,14 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
runCurrent()
advanceUntilIdle()
}
+
+ private fun getNewPendingIntent(): PendingIntent {
+ val intent = Intent().setAction(null)
+ return PendingIntent.getBroadcast(
+ mContext,
+ 1,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE,
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt
index 0c8d88065a73..175e8d4331a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt
@@ -169,7 +169,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
context.orCreateTestableResources.addOverride(
R.drawable.ic_media_home_devices,
- OTHER_DEVICE_ICON_STUB
+ OTHER_DEVICE_ICON_STUB,
)
}
@@ -384,7 +384,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
deviceCallback.onAboutToConnectDeviceAdded(
"fakeAddress",
"AboutToConnectDeviceName",
- mock(Drawable::class.java)
+ mock(Drawable::class.java),
)
// Run and reset the executors and listeners so we only focus on new events.
fakeBgExecutor.runAllReady()
@@ -423,7 +423,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
}
@Test
- @EnableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
+ @EnableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX)
fun onMediaDataLoaded_withRemotePlaybackType_usesNonNullRoutingSessionName_drawableReused() {
whenever(routingSession.name).thenReturn(REMOTE_DEVICE_NAME)
whenever(routingSession.selectedRoutes).thenReturn(listOf("selectedRoute", "selectedRoute"))
@@ -437,7 +437,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
}
@Test
- @DisableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
+ @DisableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX)
fun onMediaDataLoaded_withRemotePlaybackType_usesNonNullRoutingSessionName_drawableNotReused() {
whenever(routingSession.name).thenReturn(REMOTE_DEVICE_NAME)
whenever(routingSession.selectedRoutes).thenReturn(listOf("selectedRoute", "selectedRoute"))
@@ -479,7 +479,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Test
@RequiresFlagsEnabled(FLAG_USE_PLAYBACK_INFO_FOR_ROUTING_CONTROLS)
- @EnableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
+ @EnableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX)
fun onMediaDataLoaded_withRemotePlaybackInfo_noMatchingRoutingSession_drawableReused() {
whenever(playbackInfo.playbackType).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE)
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
@@ -494,7 +494,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Test
@RequiresFlagsEnabled(FLAG_USE_PLAYBACK_INFO_FOR_ROUTING_CONTROLS)
- @DisableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
+ @DisableFlags(com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX)
fun onMediaDataLoaded_withRemotePlaybackInfo_noMatchingRoutingSession_drawableNotReused() {
whenever(playbackInfo.playbackType).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE)
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
@@ -856,7 +856,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@DisableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
@EnableFlags(
Flags.FLAG_ENABLE_LE_AUDIO_SHARING,
- com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE
+ com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX,
)
fun onBroadcastStarted_currentMediaDeviceDataIsBroadcasting_drawablesReused() {
val broadcastCallback = setupBroadcastCallback()
@@ -874,7 +874,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Test
@DisableFlags(
Flags.FLAG_LEGACY_LE_AUDIO_SHARING,
- com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE
+ com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX,
)
@EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
fun onBroadcastStarted_currentMediaDeviceDataIsBroadcasting_drawablesNotReused() {
@@ -893,7 +893,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Test
@EnableFlags(
Flags.FLAG_LEGACY_LE_AUDIO_SHARING,
- com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE
+ com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX,
)
@DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
fun onBroadcastStarted_legacy_currentMediaDeviceDataIsNotBroadcasting_drawableReused() {
@@ -913,7 +913,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@EnableFlags(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
@DisableFlags(
Flags.FLAG_ENABLE_LE_AUDIO_SHARING,
- com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE
+ com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE_BUGFIX,
)
fun onBroadcastStarted_legacy_currentMediaDeviceDataIsNotBroadcasting_drawableNotReused() {
val broadcastCallback = setupBroadcastCallback()
@@ -984,7 +984,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
override fun onBroadcastMetadataChanged(
broadcastId: Int,
- metadata: BluetoothLeBroadcastMetadata
+ metadata: BluetoothLeBroadcastMetadata,
) {}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
index 33b61a098bc5..6c8a46f19f2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
@@ -39,7 +39,6 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
@@ -79,7 +78,6 @@ import com.google.common.truth.Truth.assertThat
import java.util.Locale
import javax.inject.Provider
import junit.framework.Assert.assertEquals
-import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -215,7 +213,6 @@ class MediaCarouselControllerTest(flags: FlagsParameterization) : SysuiTestCase(
verify(mediaHostStatesManager).addCallback(capture(hostStateCallback))
whenever(mediaControlPanelFactory.get()).thenReturn(panel)
whenever(panel.mediaViewController).thenReturn(mediaViewController)
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
MediaPlayerData.clear()
FakeExecutor.exhaustExecutors(bgExecutor)
FakeExecutor.exhaustExecutors(uiExecutor)
@@ -834,47 +831,6 @@ class MediaCarouselControllerTest(flags: FlagsParameterization) : SysuiTestCase(
verify(pageIndicator, times(4)).setNumPages(any())
}
- @DisableSceneContainer
- @Test
- fun testRecommendation_persistentEnabled_newSmartspaceLoaded_updatesSort() {
- verify(mediaDataManager).addListener(capture(listener))
-
- testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded()
-
- // When an update to existing smartspace data is loaded
- listener.value.onSmartspaceMediaDataLoaded(
- SMARTSPACE_KEY,
- EMPTY_SMARTSPACE_MEDIA_DATA.copy(isActive = true),
- true,
- )
-
- // Then the carousel is updated
- assertTrue(MediaPlayerData.playerKeys().elementAt(0).data.active)
- assertTrue(MediaPlayerData.visiblePlayerKeys().elementAt(0).data.active)
- }
-
- @DisableSceneContainer
- @Test
- fun testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded() {
- verify(mediaDataManager).addListener(capture(listener))
-
- whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
-
- // When inactive smartspace data is loaded
- listener.value.onSmartspaceMediaDataLoaded(
- SMARTSPACE_KEY,
- EMPTY_SMARTSPACE_MEDIA_DATA,
- false,
- )
-
- // Then it is added to the carousel with correct state
- assertTrue(MediaPlayerData.playerKeys().elementAt(0).isSsMediaRec)
- assertFalse(MediaPlayerData.playerKeys().elementAt(0).data.active)
-
- assertTrue(MediaPlayerData.visiblePlayerKeys().elementAt(0).isSsMediaRec)
- assertFalse(MediaPlayerData.visiblePlayerKeys().elementAt(0).data.active)
- }
-
@Test
fun testOnLockDownMode_hideMediaCarousel() {
whenever(keyguardUpdateMonitor.isUserInLockdown(context.userId)).thenReturn(true)
@@ -900,7 +856,6 @@ class MediaCarouselControllerTest(flags: FlagsParameterization) : SysuiTestCase(
@Test
fun testKeyguardGone_showMediaCarousel() =
kosmos.testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
var updatedVisibility = false
mediaCarouselController.updateHostVisibility = { updatedVisibility = true }
mediaCarouselController.mediaCarousel = mediaCarousel
@@ -923,7 +878,6 @@ class MediaCarouselControllerTest(flags: FlagsParameterization) : SysuiTestCase(
@Test
fun testKeyguardGone_showMediaCarousel_scene_container() =
kosmos.testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
var updatedVisibility = false
mediaCarouselController.updateHostVisibility = { updatedVisibility = true }
mediaCarouselController.mediaCarousel = mediaCarousel
@@ -940,7 +894,6 @@ class MediaCarouselControllerTest(flags: FlagsParameterization) : SysuiTestCase(
@Test
fun keyguardShowing_notAllowedOnLockscreen_updateVisibility() {
kosmos.testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
var updatedVisibility = false
mediaCarouselController.updateHostVisibility = { updatedVisibility = true }
mediaCarouselController.mediaCarousel = mediaCarousel
@@ -969,7 +922,6 @@ class MediaCarouselControllerTest(flags: FlagsParameterization) : SysuiTestCase(
@Test
fun keyguardShowing_allowedOnLockscreen_updateVisibility() {
kosmos.testScope.runTest {
- kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
var updatedVisibility = false
mediaCarouselController.updateHostVisibility = { updatedVisibility = true }
mediaCarouselController.mediaCarousel = mediaCarousel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
index d59a404b15bb..0924df2538e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
@@ -52,7 +52,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.views.NavigationBar;
-import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.recents.LauncherProxyService;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -109,7 +109,7 @@ public class NavigationBarControllerImplTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mNavigationBarController = spy(
new NavigationBarControllerImpl(mContext,
- mock(OverviewProxyService.class),
+ mock(LauncherProxyService.class),
mock(NavigationModeController.class),
mock(SysUiState.class),
mCommandQueue,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManagerTest.kt
index a192446e535b..50b8f37f8d25 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDetailsContentManagerTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.qs.tiles.dialog
import android.content.Intent
import android.os.Handler
import android.os.fakeExecutorHandler
+import android.platform.test.annotations.EnableFlags
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.telephonyManager
@@ -38,8 +39,7 @@ import com.android.internal.logging.UiEventLogger
import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.DialogTransitionAnimator
-import com.android.systemui.flags.setFlagValue
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -62,6 +62,8 @@ import org.mockito.kotlin.whenever
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper(setAsMainLooper = true)
+@EnableSceneContainer
+@EnableFlags(Flags.FLAG_QS_TILE_DETAILED_VIEW, Flags.FLAG_DUAL_SHADE)
@UiThreadTest
class InternetDetailsContentManagerTest : SysuiTestCase() {
private val kosmos = Kosmos()
@@ -74,11 +76,8 @@ class InternetDetailsContentManagerTest : SysuiTestCase() {
private val internetDetailsContentController: InternetDetailsContentController =
mock<InternetDetailsContentController>()
private val keyguard: KeyguardStateController = mock<KeyguardStateController>()
- private val dialogTransitionAnimator: DialogTransitionAnimator =
- mock<DialogTransitionAnimator>()
private val bgExecutor = FakeExecutor(FakeSystemClock())
private lateinit var internetDetailsContentManager: InternetDetailsContentManager
- private var subTitle: View? = null
private var ethernet: LinearLayout? = null
private var mobileDataLayout: LinearLayout? = null
private var mobileToggleSwitch: Switch? = null
@@ -96,8 +95,6 @@ class InternetDetailsContentManagerTest : SysuiTestCase() {
@Before
fun setUp() {
- // TODO: b/377388104 enable this flag after integrating with details view.
- mSetFlagsRule.setFlagValue(Flags.FLAG_QS_TILE_DETAILED_VIEW, false)
whenever(telephonyManager.createForSubscriptionId(ArgumentMatchers.anyInt()))
.thenReturn(telephonyManager)
whenever(internetWifiEntry.title).thenReturn(WIFI_TITLE)
@@ -133,9 +130,7 @@ class InternetDetailsContentManagerTest : SysuiTestCase() {
canConfigWifi = true,
coroutineScope = scope,
context = mContext,
- internetDialog = null,
uiEventLogger = mock<UiEventLogger>(),
- dialogTransitionAnimator = dialogTransitionAnimator,
handler = handler,
backgroundExecutor = bgExecutor,
keyguard = keyguard,
@@ -146,7 +141,6 @@ class InternetDetailsContentManagerTest : SysuiTestCase() {
internetDetailsContentManager.connectedWifiEntry = internetWifiEntry
internetDetailsContentManager.wifiEntriesCount = wifiEntries.size
- subTitle = contentView.requireViewById(R.id.internet_dialog_subtitle)
ethernet = contentView.requireViewById(R.id.ethernet_layout)
mobileDataLayout = contentView.requireViewById(R.id.mobile_network_layout)
mobileToggleSwitch = contentView.requireViewById(R.id.mobile_toggle)
@@ -185,32 +179,6 @@ class InternetDetailsContentManagerTest : SysuiTestCase() {
}
@Test
- fun updateContent_withApmOn_internetDialogSubTitleGone() {
- whenever(internetDetailsContentController.isAirplaneModeEnabled).thenReturn(true)
- internetDetailsContentManager.updateContent(true)
- bgExecutor.runAllReady()
-
- internetDetailsContentManager.internetContentData.observe(
- internetDetailsContentManager.lifecycleOwner!!
- ) {
- assertThat(subTitle!!.visibility).isEqualTo(View.VISIBLE)
- }
- }
-
- @Test
- fun updateContent_withApmOff_internetDialogSubTitleVisible() {
- whenever(internetDetailsContentController.isAirplaneModeEnabled).thenReturn(false)
- internetDetailsContentManager.updateContent(true)
- bgExecutor.runAllReady()
-
- internetDetailsContentManager.internetContentData.observe(
- internetDetailsContentManager.lifecycleOwner!!
- ) {
- assertThat(subTitle!!.visibility).isEqualTo(View.VISIBLE)
- }
- }
-
- @Test
fun updateContent_apmOffAndHasEthernet_showEthernet() {
whenever(internetDetailsContentController.isAirplaneModeEnabled).thenReturn(false)
whenever(internetDetailsContentController.hasEthernet()).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt
index 4e1ccfb07220..69b762b470b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/LauncherProxyServiceTest.kt
@@ -40,11 +40,11 @@ import com.android.systemui.model.sceneContainerPlugin
import com.android.systemui.navigationbar.NavigationBarController
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.process.ProcessWrapper
-import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP
+import com.android.systemui.recents.LauncherProxyService.ACTION_QUICKSTEP
import com.android.systemui.settings.FakeDisplayTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.ShadeViewController
-import com.android.systemui.shared.recents.IOverviewProxy
+import com.android.systemui.shared.recents.ILauncherProxy
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK
import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_ASLEEP
import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_AWAKE
@@ -83,12 +83,12 @@ import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-class OverviewProxyServiceTest : SysuiTestCase() {
+class LauncherProxyServiceTest : SysuiTestCase() {
@Main private val executor: Executor = MoreExecutors.directExecutor()
private val kosmos = testKosmos()
- private lateinit var subject: OverviewProxyService
+ private lateinit var subject: LauncherProxyService
@Mock private val dumpManager = DumpManager()
@Mock private val processWrapper = ProcessWrapper()
private val displayTracker = FakeDisplayTracker(mContext)
@@ -97,10 +97,10 @@ class OverviewProxyServiceTest : SysuiTestCase() {
private val wakefulnessLifecycle =
WakefulnessLifecycle(mContext, null, fakeSystemClock, dumpManager)
- @Mock private lateinit var overviewProxy: IOverviewProxy.Stub
+ @Mock private lateinit var launcherProxy: ILauncherProxy.Stub
@Mock private lateinit var packageManager: PackageManager
- // The following mocks belong to not-yet-tested parts of OverviewProxyService.
+ // The following mocks belong to not-yet-tested parts of LauncherProxyService.
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var shellInterface: ShellInterface
@Mock private lateinit var navBarController: NavigationBarController
@@ -127,18 +127,18 @@ class OverviewProxyServiceTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
val serviceComponent = ComponentName("test_package", "service_provider")
- context.addMockService(serviceComponent, overviewProxy)
+ context.addMockService(serviceComponent, launcherProxy)
context.addMockServiceResolver(
TestableContext.MockServiceResolver {
if (it.action == ACTION_QUICKSTEP) serviceComponent else null
}
)
- whenever(overviewProxy.queryLocalInterface(ArgumentMatchers.anyString()))
- .thenReturn(overviewProxy)
- whenever(overviewProxy.asBinder()).thenReturn(overviewProxy)
+ whenever(launcherProxy.queryLocalInterface(ArgumentMatchers.anyString()))
+ .thenReturn(launcherProxy)
+ whenever(launcherProxy.asBinder()).thenReturn(launcherProxy)
// packageManager.resolveServiceAsUser has to return non-null for
- // OverviewProxyService#isEnabled to become true.
+ // LauncherProxyService#isEnabled to become true.
context.setMockPackageManager(packageManager)
whenever(packageManager.resolveServiceAsUser(any(), anyInt(), anyInt()))
.thenReturn(mock(ResolveInfo::class.java))
@@ -147,7 +147,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
// return isSystemUser as true by default.
`when`(processWrapper.isSystemUser).thenReturn(true)
- subject = createOverviewProxyService(context)
+ subject = createLauncherProxyService(context)
}
@After
@@ -159,11 +159,11 @@ class OverviewProxyServiceTest : SysuiTestCase() {
fun wakefulnessLifecycle_dispatchFinishedWakingUpSetsSysUIflagToAWAKE() {
// WakefulnessLifecycle is initialized to AWAKE initially, and won't emit a noop.
wakefulnessLifecycle.dispatchFinishedGoingToSleep()
- clearInvocations(overviewProxy)
+ clearInvocations(launcherProxy)
wakefulnessLifecycle.dispatchFinishedWakingUp()
- verify(overviewProxy)
+ verify(launcherProxy)
.onSystemUiStateChanged(
longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_AWAKE }
)
@@ -173,7 +173,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
fun wakefulnessLifecycle_dispatchStartedWakingUpSetsSysUIflagToWAKING() {
wakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN)
- verify(overviewProxy)
+ verify(launcherProxy)
.onSystemUiStateChanged(
longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_WAKING }
)
@@ -183,7 +183,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
fun wakefulnessLifecycle_dispatchFinishedGoingToSleepSetsSysUIflagToASLEEP() {
wakefulnessLifecycle.dispatchFinishedGoingToSleep()
- verify(overviewProxy)
+ verify(launcherProxy)
.onSystemUiStateChanged(
longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_ASLEEP }
)
@@ -195,56 +195,56 @@ class OverviewProxyServiceTest : SysuiTestCase() {
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON
)
- verify(overviewProxy)
+ verify(launcherProxy)
.onSystemUiStateChanged(
longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_GOING_TO_SLEEP }
)
}
@Test
- fun connectToOverviewService_primaryUserNoVisibleBgUsersSupported_expectBindService() {
+ fun connectToLauncherService_primaryUserNoVisibleBgUsersSupported_expectBindService() {
`when`(processWrapper.isSystemUser).thenReturn(true)
`when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(false)
val spyContext = spy(context)
- val ops = createOverviewProxyService(spyContext)
+ val ops = createLauncherProxyService(spyContext)
ops.startConnectionToCurrentUser()
verify(spyContext, atLeast(1)).bindServiceAsUser(any(), any(), anyInt(), any())
}
@Test
- fun connectToOverviewService_nonPrimaryUserNoVisibleBgUsersSupported_expectNoBindService() {
+ fun connectToLauncherService_nonPrimaryUserNoVisibleBgUsersSupported_expectNoBindService() {
`when`(processWrapper.isSystemUser).thenReturn(false)
`when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(false)
val spyContext = spy(context)
- val ops = createOverviewProxyService(spyContext)
+ val ops = createLauncherProxyService(spyContext)
ops.startConnectionToCurrentUser()
verify(spyContext, times(0)).bindServiceAsUser(any(), any(), anyInt(), any())
}
@Test
- fun connectToOverviewService_nonPrimaryBgUserVisibleBgUsersSupported_expectBindService() {
+ fun connectToLauncherService_nonPrimaryBgUserVisibleBgUsersSupported_expectBindService() {
`when`(processWrapper.isSystemUser).thenReturn(false)
`when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(true)
`when`(userManager.isUserForeground()).thenReturn(false)
val spyContext = spy(context)
- val ops = createOverviewProxyService(spyContext)
+ val ops = createLauncherProxyService(spyContext)
ops.startConnectionToCurrentUser()
verify(spyContext, atLeast(1)).bindServiceAsUser(any(), any(), anyInt(), any())
}
@Test
- fun connectToOverviewService_nonPrimaryFgUserVisibleBgUsersSupported_expectNoBindService() {
+ fun connectToLauncherService_nonPrimaryFgUserVisibleBgUsersSupported_expectNoBindService() {
`when`(processWrapper.isSystemUser).thenReturn(false)
`when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(true)
`when`(userManager.isUserForeground()).thenReturn(true)
val spyContext = spy(context)
- val ops = createOverviewProxyService(spyContext)
+ val ops = createLauncherProxyService(spyContext)
ops.startConnectionToCurrentUser()
verify(spyContext, times(0)).bindServiceAsUser(any(), any(), anyInt(), any())
}
- private fun createOverviewProxyService(ctx: Context): OverviewProxyService {
- return OverviewProxyService(
+ private fun createLauncherProxyService(ctx: Context): LauncherProxyService {
+ return LauncherProxyService(
ctx,
executor,
commandQueue,
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 70450d29c74e..49d6909c1f93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -254,6 +254,7 @@ class NotificationShadeWindowViewControllerTest(flags: FlagsParameterization) :
mock(BouncerViewBinder::class.java),
{ mock(ConfigurationForwarder::class.java) },
brightnessMirrorShowingInteractor,
+ kosmos.testDispatcher,
)
underTest.setupExpandedStatusBar()
underTest.setDragDownHelper(dragDownHelper)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
index a04ca038021e..9abe9aa5e598 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
@@ -32,8 +32,8 @@ import com.android.systemui.fragments.FragmentService
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener
import com.android.systemui.plugins.qs.QS
-import com.android.systemui.recents.OverviewProxyService
-import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
+import com.android.systemui.recents.LauncherProxyService
+import com.android.systemui.recents.LauncherProxyService.LauncherProxyListener
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
@@ -71,7 +71,7 @@ class NotificationsQSContainerControllerLegacyTest : SysuiTestCase() {
private val view = mock<NotificationsQuickSettingsContainer>()
private val navigationModeController = mock<NavigationModeController>()
- private val overviewProxyService = mock<OverviewProxyService>()
+ private val mLauncherProxyService = mock<LauncherProxyService>()
private val shadeHeaderController = mock<ShadeHeaderController>()
private val shadeInteractor = mock<ShadeInteractor>()
private val fragmentService = mock<FragmentService>()
@@ -81,7 +81,7 @@ class NotificationsQSContainerControllerLegacyTest : SysuiTestCase() {
private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>()
@Captor lateinit var navigationModeCaptor: ArgumentCaptor<ModeChangedListener>
- @Captor lateinit var taskbarVisibilityCaptor: ArgumentCaptor<OverviewProxyListener>
+ @Captor lateinit var taskbarVisibilityCaptor: ArgumentCaptor<LauncherProxyListener>
@Captor lateinit var windowInsetsCallbackCaptor: ArgumentCaptor<Consumer<WindowInsets>>
@Captor lateinit var constraintSetCaptor: ArgumentCaptor<ConstraintSet>
@Captor lateinit var attachStateListenerCaptor: ArgumentCaptor<View.OnAttachStateChangeListener>
@@ -89,7 +89,7 @@ class NotificationsQSContainerControllerLegacyTest : SysuiTestCase() {
lateinit var underTest: NotificationsQSContainerController
private lateinit var navigationModeCallback: ModeChangedListener
- private lateinit var taskbarVisibilityCallback: OverviewProxyListener
+ private lateinit var taskbarVisibilityCallback: LauncherProxyListener
private lateinit var windowInsetsCallback: Consumer<WindowInsets>
private lateinit var fakeSystemClock: FakeSystemClock
private lateinit var delayableExecutor: FakeExecutor
@@ -110,7 +110,7 @@ class NotificationsQSContainerControllerLegacyTest : SysuiTestCase() {
NotificationsQSContainerController(
view,
navigationModeController,
- overviewProxyService,
+ mLauncherProxyService,
shadeHeaderController,
shadeInteractor,
fragmentService,
@@ -127,7 +127,7 @@ class NotificationsQSContainerControllerLegacyTest : SysuiTestCase() {
overrideResource(R.dimen.qs_footer_action_inset, FOOTER_ACTIONS_INSET)
whenever(navigationModeController.addListener(navigationModeCaptor.capture()))
.thenReturn(GESTURES_NAVIGATION)
- doNothing().`when`(overviewProxyService).addCallback(taskbarVisibilityCaptor.capture())
+ doNothing().`when`(mLauncherProxyService).addCallback(taskbarVisibilityCaptor.capture())
doNothing().`when`(view).setInsetsChangedListener(windowInsetsCallbackCaptor.capture())
doNothing().`when`(view).applyConstraints(constraintSetCaptor.capture())
doNothing().`when`(view).addOnAttachStateChangeListener(attachStateListenerCaptor.capture())
@@ -402,7 +402,7 @@ class NotificationsQSContainerControllerLegacyTest : SysuiTestCase() {
NotificationsQSContainerController(
container,
navigationModeController,
- overviewProxyService,
+ mLauncherProxyService,
shadeHeaderController,
shadeInteractor,
fragmentService,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
index 24f8843e935d..4c12cc886e33 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
@@ -32,8 +32,8 @@ import com.android.systemui.fragments.FragmentService
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener
import com.android.systemui.plugins.qs.QS
-import com.android.systemui.recents.OverviewProxyService
-import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
+import com.android.systemui.recents.LauncherProxyService
+import com.android.systemui.recents.LauncherProxyService.LauncherProxyListener
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
@@ -70,7 +70,7 @@ class NotificationsQSContainerControllerTest : SysuiTestCase() {
private val view = mock<NotificationsQuickSettingsContainer>()
private val navigationModeController = mock<NavigationModeController>()
- private val overviewProxyService = mock<OverviewProxyService>()
+ private val mLauncherProxyService = mock<LauncherProxyService>()
private val shadeHeaderController = mock<ShadeHeaderController>()
private val shadeInteractor = mock<ShadeInteractor>()
private val fragmentService = mock<FragmentService>()
@@ -80,7 +80,7 @@ class NotificationsQSContainerControllerTest : SysuiTestCase() {
private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>()
@Captor lateinit var navigationModeCaptor: ArgumentCaptor<ModeChangedListener>
- @Captor lateinit var taskbarVisibilityCaptor: ArgumentCaptor<OverviewProxyListener>
+ @Captor lateinit var taskbarVisibilityCaptor: ArgumentCaptor<LauncherProxyListener>
@Captor lateinit var windowInsetsCallbackCaptor: ArgumentCaptor<Consumer<WindowInsets>>
@Captor lateinit var constraintSetCaptor: ArgumentCaptor<ConstraintSet>
@Captor lateinit var attachStateListenerCaptor: ArgumentCaptor<View.OnAttachStateChangeListener>
@@ -88,7 +88,7 @@ class NotificationsQSContainerControllerTest : SysuiTestCase() {
lateinit var underTest: NotificationsQSContainerController
private lateinit var navigationModeCallback: ModeChangedListener
- private lateinit var taskbarVisibilityCallback: OverviewProxyListener
+ private lateinit var taskbarVisibilityCallback: LauncherProxyListener
private lateinit var windowInsetsCallback: Consumer<WindowInsets>
private lateinit var fakeSystemClock: FakeSystemClock
private lateinit var delayableExecutor: FakeExecutor
@@ -110,7 +110,7 @@ class NotificationsQSContainerControllerTest : SysuiTestCase() {
NotificationsQSContainerController(
view,
navigationModeController,
- overviewProxyService,
+ mLauncherProxyService,
shadeHeaderController,
shadeInteractor,
fragmentService,
@@ -127,7 +127,7 @@ class NotificationsQSContainerControllerTest : SysuiTestCase() {
overrideResource(R.dimen.qs_footer_action_inset, FOOTER_ACTIONS_INSET)
whenever(navigationModeController.addListener(navigationModeCaptor.capture()))
.thenReturn(GESTURES_NAVIGATION)
- doNothing().`when`(overviewProxyService).addCallback(taskbarVisibilityCaptor.capture())
+ doNothing().`when`(mLauncherProxyService).addCallback(taskbarVisibilityCaptor.capture())
doNothing().`when`(view).setInsetsChangedListener(windowInsetsCallbackCaptor.capture())
doNothing().`when`(view).applyConstraints(constraintSetCaptor.capture())
doNothing().`when`(view).addOnAttachStateChangeListener(attachStateListenerCaptor.capture())
@@ -457,7 +457,7 @@ class NotificationsQSContainerControllerTest : SysuiTestCase() {
NotificationsQSContainerController(
container,
navigationModeController,
- overviewProxyService,
+ mLauncherProxyService,
shadeHeaderController,
shadeInteractor,
fragmentService,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index a5cd81ff3116..edb0f352a64a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -71,6 +71,7 @@ import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
+import dagger.Lazy
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -197,7 +198,8 @@ class ShadeHeaderControllerTest : SysuiTestCase() {
privacyIconsController,
insetsProviderStore,
configurationController,
- kosmos.shadeDisplaysRepository,
+ viewContext,
+ Lazy { kosmos.shadeDisplaysRepository },
variableDateViewControllerFactory,
batteryMeterViewController,
dumpManager,
@@ -296,7 +298,7 @@ class ShadeHeaderControllerTest : SysuiTestCase() {
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)
+ verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
index b3a5872a7dec..57c28580c063 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
@@ -19,11 +19,11 @@ import android.graphics.Typeface
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.clocks.ClockLogger
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.shared.clocks.ClockContext
import com.android.systemui.shared.clocks.FontTextStyle
-import com.android.systemui.shared.clocks.LogUtil
import com.android.systemui.shared.clocks.TypefaceCache
import com.android.systemui.shared.clocks.view.SimpleDigitalClockTextView
import org.junit.Assert.assertEquals
@@ -34,7 +34,7 @@ import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidTestingRunner::class)
class SimpleDigitalClockTextViewTest : SysuiTestCase() {
- private val messageBuffer = LogUtil.DEBUG_MESSAGE_BUFFER
+ private val messageBuffer = ClockLogger.DEBUG_MESSAGE_BUFFER
private lateinit var underTest: SimpleDigitalClockTextView
private val defaultLargeClockTextSize = 500F
private val smallerTextSize = 300F
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 493468e8f675..77b116e2e465 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
@@ -370,7 +370,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
row.onDensityOrFontScaleChanged();
- verify(mockContainer).reInflateViews(any(), any());
+ verify(mockContainer).reInflateViews(any());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
index 1eb88c5a5616..0457255fee4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
@@ -19,10 +19,12 @@ import android.app.Notification
import android.app.Person
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
+import android.view.View.GONE
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.RankingBuilder
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePrivateSingleLineView
@@ -90,6 +92,7 @@ class SingleLineViewBinderTest : SysuiTestCase() {
builder = notificationBuilder,
systemUiContext = context,
redactText = false,
+ summarization = null
)
// WHEN: binds the viewHolder
@@ -151,6 +154,7 @@ class SingleLineViewBinderTest : SysuiTestCase() {
builder = notificationBuilder,
systemUiContext = context,
redactText = false,
+ summarization = null
)
// WHEN: binds the view
SingleLineViewBinder.bind(viewModel, view)
@@ -200,6 +204,7 @@ class SingleLineViewBinderTest : SysuiTestCase() {
builder = notificationBuilder,
systemUiContext = context,
redactText = false,
+ summarization = null
)
// WHEN: binds the view with the view model
SingleLineViewBinder.bind(viewModel, view)
@@ -211,6 +216,70 @@ class SingleLineViewBinderTest : SysuiTestCase() {
assertNull(viewModel.conversationData)
}
+ @Test
+ @EnableFlags(AsyncHybridViewInflation.FLAG_NAME, android.app.Flags.FLAG_NM_SUMMARIZATION_UI,
+ android.app.Flags.FLAG_NM_SUMMARIZATION)
+ fun bindSummarizedGroupConversationSingleLineView() {
+ // GIVEN a row with a group conversation notification
+ val user =
+ Person.Builder()
+ .setName(USER_NAME)
+ .build()
+ val style =
+ Notification.MessagingStyle(user)
+ .addMessage(MESSAGE_TEXT, System.currentTimeMillis(), user)
+ .addMessage(
+ "How about lunch?",
+ System.currentTimeMillis(),
+ Person.Builder().setName("user2").build(),
+ )
+ .setGroupConversation(true)
+ notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID)
+ val notification = notificationBuilder.build()
+ val row = helper.createRow(notification)
+ val rb = RankingBuilder(row.entry.ranking)
+ rb.setSummarization("summary!")
+ row.entry.ranking = rb.build()
+
+ val view =
+ inflatePrivateSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock(),
+ )
+ as HybridConversationNotificationView
+
+ val publicView =
+ inflatePublicSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock(),
+ )
+ as HybridConversationNotificationView
+ assertNotNull(publicView)
+
+ val viewModel =
+ SingleLineViewInflater.inflateSingleLineViewModel(
+ notification = notification,
+ messagingStyle = style,
+ builder = notificationBuilder,
+ systemUiContext = context,
+ redactText = false,
+ summarization = "summary"
+ )
+ // WHEN: binds the view
+ SingleLineViewBinder.bind(viewModel, view)
+
+ // THEN: the single-line conversation view should only include summarization content
+ assertEquals(viewModel.conversationData?.summarization, view.textView.text)
+ assertEquals("", view.conversationSenderNameView.text)
+ assertEquals(GONE, view.conversationSenderNameView.visibility)
+ }
+
private companion object {
const val CHANNEL_ID = "CHANNEL_ID"
const val CONTENT_TITLE = "A Cool New Feature"
@@ -218,5 +287,6 @@ class SingleLineViewBinderTest : SysuiTestCase() {
const val USER_NAME = "USER_NAME"
const val MESSAGE_TEXT = "MESSAGE_TEXT"
const val SHORTCUT_ID = "Shortcut"
+ const val SUMMARIZATION = "summarization"
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt
index ef70e277832e..13724a8b44da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt
@@ -272,6 +272,35 @@ class SingleLineViewInflaterTest : SysuiTestCase() {
}
}
+ @Test
+ fun createViewModelForSummarizedConversationNotification() {
+ // Given: a non-group conversation notification
+ val notificationType = OneToOneConversation()
+ val notification = getNotification(notificationType)
+
+ // When: inflate the SingleLineViewModel
+ val singleLineViewModel = notification.makeSingleLineViewModel(notificationType)
+
+ // Then: the inflated SingleLineViewModel should be as expected
+ // titleText: Notification.ConversationTitle
+ // contentText: the last message text
+ // conversationSenderName: null, because it's not a group conversation
+ // conversationData.avatar: a single icon of the last sender
+ // summarizedText: the summary text from the ranking
+ assertEquals(CONVERSATION_TITLE, singleLineViewModel.titleText)
+ assertEquals(LAST_MESSAGE, singleLineViewModel.contentText)
+ assertNull(
+ singleLineViewModel.conversationData?.conversationSenderName,
+ "Sender name should be null for one-on-one conversation"
+ )
+ assertTrue {
+ singleLineViewModel.conversationData
+ ?.avatar
+ ?.equalsTo(SingleIcon(firstSenderIcon.loadDrawable(context))) == true
+ }
+ assertEquals("summary", singleLineViewModel.conversationData?.summarization)
+ }
+
sealed class NotificationType(val largeIcon: Icon? = null)
class NonMessaging(largeIcon: Icon? = null) : NotificationType(largeIcon)
@@ -380,7 +409,8 @@ class SingleLineViewInflaterTest : SysuiTestCase() {
if (isConversation) messagingStyle else null,
builder,
context,
- false
+ false,
+ "summary"
)
}
diff --git a/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt b/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt
index de4bbecaaf0e..42c509eeaa0b 100644
--- a/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt
+++ b/packages/SystemUI/tests/utils/src/android/hardware/input/FakeInputManager.kt
@@ -16,16 +16,19 @@
package android.hardware.input
+import android.hardware.input.InputGestureData.Trigger
+import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_ALREADY_EXISTS
+import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_DOES_NOT_EXIST
+import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
import android.hardware.input.InputManager.InputDeviceListener
import android.view.InputDevice
import android.view.KeyCharacterMap
import android.view.KeyCharacterMap.VIRTUAL_KEYBOARD
import android.view.KeyEvent
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.invocation.InvocationOnMock
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
class FakeInputManager {
@@ -49,36 +52,79 @@ class FakeInputManager {
)
private var inputDeviceListener: InputDeviceListener? = null
+ private val customInputGestures: MutableMap<Trigger, InputGestureData> = mutableMapOf()
+ var addCustomInputGestureErrorCode = CUSTOM_INPUT_GESTURE_RESULT_ERROR_ALREADY_EXISTS
+
+ val inputManager: InputManager = mock {
+ on { getCustomInputGestures(any()) }.then { customInputGestures.values.toList() }
+
+ on { addCustomInputGesture(any()) }
+ .then {
+ val inputGestureData = it.getArgument<InputGestureData>(0)
+ val trigger = inputGestureData.trigger
+
+ if (customInputGestures.containsKey(trigger)) {
+ addCustomInputGestureErrorCode
+ } else {
+ customInputGestures[trigger] = inputGestureData
+ CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
+ }
+ }
+
+ on { removeCustomInputGesture(any()) }
+ .then {
+ val inputGestureData = it.getArgument<InputGestureData>(0)
+ val trigger = inputGestureData.trigger
+
+ if (customInputGestures.containsKey(trigger)) {
+ customInputGestures.remove(trigger)
+ CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
+ } else {
+ CUSTOM_INPUT_GESTURE_RESULT_ERROR_DOES_NOT_EXIST
+ }
+ }
+
+ on { removeAllCustomInputGestures(any()) }.then { customInputGestures.clear() }
- val inputManager =
- mock<InputManager> {
- whenever(getInputDevice(anyInt())).thenAnswer { invocation ->
+ on { getInputGesture(any()) }
+ .then {
+ val trigger = it.getArgument<Trigger>(0)
+ customInputGestures[trigger]
+ }
+
+ on { getInputDevice(anyInt()) }
+ .thenAnswer { invocation ->
val deviceId = invocation.arguments[0] as Int
return@thenAnswer devices[deviceId]
}
- whenever(inputDeviceIds).thenAnswer {
+ on { inputDeviceIds }
+ .thenAnswer {
return@thenAnswer devices.keys.toIntArray()
}
- fun setDeviceEnabled(invocation: InvocationOnMock, enabled: Boolean) {
- val deviceId = invocation.arguments[0] as Int
- val device = devices[deviceId] ?: return
- devices[deviceId] = device.copy(enabled = enabled)
- }
+ fun setDeviceEnabled(invocation: InvocationOnMock, enabled: Boolean) {
+ val deviceId = invocation.arguments[0] as Int
+ val device = devices[deviceId] ?: return
+ devices[deviceId] = device.copy(enabled = enabled)
+ }
- whenever(disableInputDevice(anyInt())).thenAnswer { invocation ->
- setDeviceEnabled(invocation, enabled = false)
- }
- whenever(enableInputDevice(anyInt())).thenAnswer { invocation ->
- setDeviceEnabled(invocation, enabled = true)
- }
- whenever(deviceHasKeys(any(), any())).thenAnswer { invocation ->
+ on { disableInputDevice(anyInt()) }
+ .thenAnswer { invocation -> setDeviceEnabled(invocation, enabled = false) }
+ on { enableInputDevice(anyInt()) }
+ .thenAnswer { invocation -> setDeviceEnabled(invocation, enabled = true) }
+ on { deviceHasKeys(any(), any()) }
+ .thenAnswer { invocation ->
val deviceId = invocation.arguments[0] as Int
val keyCodes = invocation.arguments[1] as IntArray
val supportedKeyCodes = supportedKeyCodesByDeviceId[deviceId]!!
return@thenAnswer keyCodes.map { supportedKeyCodes.contains(it) }.toBooleanArray()
}
- }
+ }
+
+ fun resetCustomInputGestures() {
+ customInputGestures.clear()
+ addCustomInputGestureErrorCode = CUSTOM_INPUT_GESTURE_RESULT_ERROR_ALREADY_EXISTS
+ }
fun addPhysicalKeyboardIfNotPresent(deviceId: Int, enabled: Boolean = true) {
if (devices.containsKey(deviceId)) {
@@ -97,7 +143,7 @@ class FakeInputManager {
vendorId: Int = 0,
productId: Int = 0,
isFullKeyboard: Boolean = true,
- enabled: Boolean = true
+ enabled: Boolean = true,
) {
check(id > 0) { "Physical keyboard ids have to be > 0" }
addKeyboard(id, vendorId, productId, isFullKeyboard, enabled)
@@ -113,7 +159,7 @@ class FakeInputManager {
vendorId: Int = 0,
productId: Int = 0,
isFullKeyboard: Boolean = true,
- enabled: Boolean = true
+ enabled: Boolean = true,
) {
val keyboardType =
if (isFullKeyboard) InputDevice.KEYBOARD_TYPE_ALPHABETIC
@@ -152,7 +198,7 @@ class FakeInputManager {
id: Int = getId(),
type: Int = keyboardType,
sources: Int = getSources(),
- enabled: Boolean = isEnabled
+ enabled: Boolean = isEnabled,
) =
InputDevice.Builder()
.setId(id)
diff --git a/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt b/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt
index 7ed736158a53..76fc61185b49 100644
--- a/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt
+++ b/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt
@@ -433,10 +433,6 @@ class FakeStatusBarService : IStatusBarService.Stub() {
override fun showRearDisplayDialog(currentBaseState: Int) {}
- override fun unbundleNotification(key: String) {}
-
- override fun rebundleNotification(key: String) {}
-
companion object {
const val DEFAULT_DISPLAY_ID = Display.DEFAULT_DISPLAY
const val SECONDARY_DISPLAY_ID = 2
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryKosmos.kt
index 5da6c7b1f2a8..ea0dc6c60a3f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryKosmos.kt
@@ -18,12 +18,23 @@ package com.android.systemui.communal.data.repository
import android.app.admin.devicePolicyManager
import android.content.res.mainResources
+import com.android.systemui.Flags
import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.flags.featureFlagsClassic
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.util.settings.fakeSettings
+val Kosmos.communalDefaultBackground: CommunalBackgroundType by
+ Kosmos.Fixture {
+ if (Flags.glanceableHubBlurredBackground()) {
+ CommunalBackgroundType.BLUR
+ } else {
+ CommunalBackgroundType.ANIMATED
+ }
+ }
+
val Kosmos.communalSettingsRepository: CommunalSettingsRepository by
Kosmos.Fixture {
CommunalSettingsRepositoryImpl(
@@ -33,5 +44,6 @@ val Kosmos.communalSettingsRepository: CommunalSettingsRepository by
secureSettings = fakeSettings,
broadcastDispatcher = broadcastDispatcher,
devicePolicyManager = devicePolicyManager,
+ defaultBackgroundType = communalDefaultBackground,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt
index 93e7f2e588b0..83f4e8f5aa49 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt
@@ -25,7 +25,7 @@ import com.android.systemui.keyboard.data.repository.keyboardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
-import com.android.systemui.recents.OverviewProxyService
+import com.android.systemui.recents.LauncherProxyService
import com.android.systemui.touchpad.data.repository.touchpadRepository
import com.android.systemui.user.data.repository.userRepository
import org.mockito.kotlin.mock
@@ -43,12 +43,12 @@ var Kosmos.keyboardTouchpadEduInteractor by
userRepository,
),
tutorialRepository = tutorialSchedulerRepository,
- overviewProxyService = mockOverviewProxyService,
+ launcherProxyService = mockLauncherProxyService,
metricsLogger = mockEduMetricsLogger,
clock = fakeEduClock,
)
}
var Kosmos.mockEduMetricsLogger by Kosmos.Fixture { mock<ContextualEducationMetricsLogger>() }
-var Kosmos.mockOverviewProxyService by Kosmos.Fixture { mock<OverviewProxyService>() }
+var Kosmos.mockLauncherProxyService by Kosmos.Fixture { mock<LauncherProxyService>() }
var Kosmos.mockEduInputManager by Kosmos.Fixture { mock<InputManager>() }
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 f4791003c828..026f8f97d2ae 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
@@ -124,8 +124,8 @@ class FakeKeyguardTransitionRepository(
/**
* Sends TransitionSteps between [from] and [to], calling [runCurrent] after each step.
*
- * By default, sends steps through FINISHED (STARTED, RUNNING, FINISHED) but can be halted part
- * way using [throughTransitionState].
+ * By default, sends steps through FINISHED (STARTED, RUNNING @0.5f, RUNNING @1f, FINISHED) but
+ * can be halted part way using [throughTransitionState].
*/
suspend fun sendTransitionSteps(
from: KeyguardState,
@@ -137,6 +137,25 @@ class FakeKeyguardTransitionRepository(
}
/**
+ * Sends a STARTED step between [from] and [to], followed by two RUNNING steps at value
+ * [throughValue] / 2 and [throughValue], calling [runCurrent] after each step.
+ */
+ suspend fun sendTransitionStepsThroughRunning(
+ from: KeyguardState,
+ to: KeyguardState,
+ testScope: TestScope,
+ throughValue: Float = 1f,
+ ) {
+ sendTransitionSteps(
+ from,
+ to,
+ testScope.testScheduler,
+ TransitionState.RUNNING,
+ throughValue,
+ )
+ }
+
+ /**
* Sends the provided [step] and makes sure that all previous [TransitionState]'s are sent when
* [fillInSteps] is true. e.g. when a step FINISHED is provided, a step with STARTED and RUNNING
* is also sent.
@@ -178,14 +197,15 @@ class FakeKeyguardTransitionRepository(
/**
* Sends TransitionSteps between [from] and [to], calling [runCurrent] after each step.
*
- * By default, sends steps through FINISHED (STARTED, RUNNING, FINISHED) but can be halted part
- * way using [throughTransitionState].
+ * By default, sends steps through FINISHED (STARTED, RUNNING @0.5f, RUNNING @1f, FINISHED) but
+ * can be halted part way using [throughTransitionState].
*/
suspend fun sendTransitionSteps(
from: KeyguardState,
to: KeyguardState,
testScheduler: TestCoroutineScheduler,
throughTransitionState: TransitionState = TransitionState.FINISHED,
+ throughTransitionValue: Float = 1f,
) {
val lastStep = _transitions.replayCache.lastOrNull()
if (lastStep != null && lastStep.transitionState != TransitionState.FINISHED) {
@@ -216,13 +236,14 @@ class FakeKeyguardTransitionRepository(
throughTransitionState == TransitionState.RUNNING ||
throughTransitionState == TransitionState.FINISHED
) {
+ // Send two steps to better simulate RUNNING transitions.
sendTransitionStep(
step =
TransitionStep(
transitionState = TransitionState.RUNNING,
from = from,
to = to,
- value = 0.5f,
+ value = throughTransitionValue / 2f,
)
)
testScheduler.runCurrent()
@@ -233,7 +254,7 @@ class FakeKeyguardTransitionRepository(
transitionState = TransitionState.RUNNING,
from = from,
to = to,
- value = 1f,
+ value = throughTransitionValue,
)
)
testScheduler.runCurrent()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
index a91ed0f4b904..ef9bd8282090 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
@@ -29,6 +29,7 @@ import com.android.systemui.keyguard.ui.viewmodel.keyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.keyguardSmartspaceViewModel
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.shade.LargeScreenHeaderHelper
import java.util.Optional
import org.mockito.Mockito.spy
@@ -99,6 +100,7 @@ val Kosmos.keyguardBlueprintRepository by
blueprints = setOf(defaultKeyguardBlueprint, splitShadeBlueprint),
handler = fakeExecutorHandler,
assert = mock(),
+ log = logcatLogBuffer("blueprints"),
)
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/GlanceableHubBlurComponentFactoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/GlanceableHubBlurComponentFactoryKosmos.kt
new file mode 100644
index 000000000000..3a04b7a0ce83
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/GlanceableHubBlurComponentFactoryKosmos.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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
+
+import com.android.systemui.keyguard.dagger.GlanceableHubBlurComponent
+import com.android.systemui.keyguard.ui.transitions.GlanceableHubBlurProvider
+import com.android.systemui.keyguard.ui.transitions.blurConfig
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.glanceableHubBlurComponentFactory by
+ Kosmos.Fixture {
+ object : GlanceableHubBlurComponent.Factory {
+ override fun create(
+ animation: KeyguardTransitionAnimationFlow.FlowBuilder
+ ): GlanceableHubBlurComponent {
+ return object : GlanceableHubBlurComponent {
+ override fun getBlurProvider(): GlanceableHubBlurProvider {
+ return GlanceableHubBlurProvider(animation, blurConfig)
+ }
+ }
+ }
+ }
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/FakeGlanceableHubTransition.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/FakeGlanceableHubTransition.kt
new file mode 100644
index 000000000000..41efd7395afa
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/FakeGlanceableHubTransition.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.transitions
+
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeGlanceableHubTransition : GlanceableHubTransition {
+ override val windowBlurRadius: MutableStateFlow<Float> = MutableStateFlow(0.0f)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt
index 87c3dbf9487e..ec75cfdd1002 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt
@@ -16,10 +16,14 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.keyguard.ui.glanceableHubBlurComponentFactory
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
val Kosmos.dozingToGlanceableHubTransitionViewModel by Fixture {
- DozingToGlanceableHubTransitionViewModel(animationFlow = keyguardTransitionAnimationFlow)
+ DozingToGlanceableHubTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
+ )
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
index 00741eb69c62..0dc99c88970e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.keyguard.ui.glanceableHubBlurComponentFactory
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
@@ -25,5 +26,6 @@ val Kosmos.dreamingToGlanceableHubTransitionViewModel by
DreamingToGlanceableHubTransitionViewModel(
configurationInteractor = configurationInteractor,
animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelKosmos.kt
new file mode 100644
index 000000000000..392bbd5b14fa
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDozingTransitionViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.keyguard.ui.glanceableHubBlurComponentFactory
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.glanceableHubToDozingTransitionViewModel by
+ Kosmos.Fixture {
+ GlanceableHubToDozingTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ blurComponentFactory = glanceableHubBlurComponentFactory,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelKosmos.kt
index 1302f155d93b..c2c9ca7f5485 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToDreamingTransitionViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.keyguard.ui.glanceableHubBlurComponentFactory
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
@@ -25,5 +26,6 @@ val Kosmos.glanceableHubToDreamingTransitionViewModel by
GlanceableHubToDreamingTransitionViewModel(
configurationInteractor = configurationInteractor,
animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt
index bb1098f14ea6..530981c489e8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.keyguard.ui.glanceableHubBlurComponentFactory
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
@@ -25,5 +26,6 @@ val Kosmos.glanceableHubToLockscreenTransitionViewModel by Fixture {
GlanceableHubToLockscreenTransitionViewModel(
configurationInteractor = configurationInteractor,
animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelKosmos.kt
new file mode 100644
index 000000000000..adb892d56286
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToOccludedTransitionViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.keyguard.ui.glanceableHubBlurComponentFactory
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.glanceableHubToOccludedTransitionViewModel by
+ Kosmos.Fixture {
+ GlanceableHubToOccludedTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt
index c1c0807c9cf2..b233d3ff9e0f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.blurConfig
import com.android.systemui.kosmos.Kosmos
@@ -25,5 +26,6 @@ val Kosmos.glanceableHubToPrimaryBouncerTransitionViewModel by Fixture {
GlanceableHubToPrimaryBouncerTransitionViewModel(
animationFlow = keyguardTransitionAnimationFlow,
blurConfig = blurConfig,
+ communalSettingsInteractor = communalSettingsInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt
index ab7ccb3bc029..b33d70298388 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt
@@ -20,6 +20,7 @@ import android.os.fakeExecutorHandler
import com.android.systemui.keyguard.domain.interactor.keyguardBlueprintInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.logcatLogBuffer
val Kosmos.keyguardBlueprintViewModel by
Kosmos.Fixture {
@@ -27,5 +28,6 @@ val Kosmos.keyguardBlueprintViewModel by
fakeExecutorHandler,
keyguardBlueprintInteractor,
keyguardTransitionInteractor,
+ blueprintLog = logcatLogBuffer("blueprints"),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt
index 0e961ccaf07b..2172d958ce3f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.keyguard.ui.glanceableHubBlurComponentFactory
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
@@ -25,5 +26,6 @@ val Kosmos.lockscreenToGlanceableHubTransitionViewModel by Fixture {
LockscreenToGlanceableHubTransitionViewModel(
configurationInteractor = configurationInteractor,
animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelKosmos.kt
new file mode 100644
index 000000000000..38e31db9aaf8
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToGlanceableHubTransitionViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.keyguard.ui.glanceableHubBlurComponentFactory
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.occludedToGlanceableHubTransitionViewModel by
+ Kosmos.Fixture {
+ OccludedToGlanceableHubTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ blurFactory = glanceableHubBlurComponentFactory,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelKosmos.kt
index 004f97d95673..c97c4e3ba302 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToPrimaryBouncerTransitionViewModelKosmos.kt
@@ -25,5 +25,6 @@ val Kosmos.occludedToPrimaryBouncerTransitionViewModel by Fixture {
OccludedToPrimaryBouncerTransitionViewModel(
animationFlow = keyguardTransitionAnimationFlow,
blurConfig = blurConfig,
+ shadeDependentFlows = shadeDependentFlows,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt
index 4fe18fb558b2..2dc579ca2134 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.blurConfig
import com.android.systemui.kosmos.Kosmos
@@ -25,5 +26,6 @@ val Kosmos.primaryBouncerToGlanceableHubTransitionViewModel by Fixture {
PrimaryBouncerToGlanceableHubTransitionViewModel(
animationFlow = keyguardTransitionAnimationFlow,
blurConfig = blurConfig,
+ communalSettingsInteractor = communalSettingsInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelKosmos.kt
index 2256c10eebc9..ed5dd454a087 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToOccludedTransitionViewModelKosmos.kt
@@ -25,5 +25,6 @@ val Kosmos.primaryBouncerToOccludedTransitionViewModel by Fixture {
PrimaryBouncerToOccludedTransitionViewModel(
animationFlow = keyguardTransitionAnimationFlow,
blurConfig = blurConfig,
+ shadeDependentFlows = shadeDependentFlows,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
index a4c2cc275e44..b255b51281af 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.kosmos
import com.android.systemui.SysuiTestCase
@@ -6,9 +24,8 @@ import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.settings.brightness.ui.BrightnessWarningToast
-import com.android.systemui.util.mockito.mock
import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
@@ -46,8 +63,6 @@ var Kosmos.backgroundCoroutineContext: CoroutineContext by Fixture {
backgroundScope.coroutineContext
}
var Kosmos.mainCoroutineContext: CoroutineContext by Fixture { testScope.coroutineContext }
-var Kosmos.brightnessWarningToast: BrightnessWarningToast by
- Kosmos.Fixture { mock<BrightnessWarningToast>() }
/**
* Run this test body with a [Kosmos] as receiver, and using the [testScope] currently installed in
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
index 01e357e1d0c8..8aa98af0b947 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
@@ -39,6 +39,7 @@ import com.android.systemui.qs.footer.foregroundServicesRepository
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.security.data.repository.securityRepository
import com.android.systemui.settings.userTracker
+import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.statusbar.policy.deviceProvisionedController
import com.android.systemui.statusbar.policy.securityController
import com.android.systemui.user.data.repository.userSwitcherRepository
@@ -94,6 +95,7 @@ val Kosmos.footerActionsViewModelFactory by Fixture {
context = applicationContext,
falsingManager = falsingManager,
footerActionsInteractor = footerActionsInteractor,
+ shadeModeInteractor = shadeModeInteractor,
globalActionsDialogLiteProvider = { mock() },
activityStarter,
showPowerButton = true,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
index 9edeb0cb1e4e..43307701b6fb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
@@ -39,8 +39,10 @@ import com.android.systemui.qs.footer.data.repository.ForegroundServicesReposito
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import com.android.systemui.qs.footer.ui.viewmodel.createFooterActionsViewModel
import com.android.systemui.security.data.repository.SecurityRepository
import com.android.systemui.security.data.repository.SecurityRepositoryImpl
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.statusbar.policy.FakeSecurityController
import com.android.systemui.statusbar.policy.FakeUserInfoController
@@ -56,6 +58,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.settings.FakeGlobalSettings
import com.android.systemui.util.settings.GlobalSettings
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestCoroutineScheduler
@@ -86,10 +89,12 @@ class FooterActionsTestUtils(
falsingManager: FalsingManager = FalsingManagerFake(),
globalActionsDialogLite: GlobalActionsDialogLite = mock(),
showPowerButton: Boolean = true,
+ shadeMode: ShadeMode,
): FooterActionsViewModel {
- return FooterActionsViewModel(
+ return createFooterActionsViewModel(
context,
footerActionsInteractor,
+ flowOf(shadeMode),
falsingManager,
globalActionsDialogLite,
mockActivityStarter,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModelKosmos.kt
index 52d8a3aac836..75ca311689ce 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModelKosmos.kt
@@ -21,6 +21,7 @@ import com.android.systemui.classifier.domain.interactor.falsingInteractor
import com.android.systemui.globalactions.globalActionsDialogLite
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.qs.footerActionsInteractor
+import com.android.systemui.shade.domain.interactor.shadeModeInteractor
val Kosmos.toolbarViewModelFactory by
Kosmos.Fixture {
@@ -31,6 +32,7 @@ val Kosmos.toolbarViewModelFactory by
footerActionsInteractor,
{ globalActionsDialogLite },
falsingInteractor,
+ shadeModeInteractor,
applicationContext,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index 72c75000ebf4..d105326ec3d0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -46,6 +46,7 @@ import com.android.systemui.scene.session.shared.shadeSessionStorage
import com.android.systemui.scene.shared.logger.sceneLogger
import com.android.systemui.settings.displayTracker
import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
import com.android.systemui.statusbar.notificationShadeWindowController
import com.android.systemui.statusbar.phone.centralSurfacesOptional
@@ -87,5 +88,6 @@ val Kosmos.sceneContainerStartable by Fixture {
msdlPlayer = msdlPlayer,
disabledContentInteractor = disabledContentInteractor,
activityTransitionAnimator = activityTransitionAnimator,
+ shadeModeInteractor = shadeModeInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
index e143324baeae..eb494f714a31 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
@@ -32,7 +32,7 @@ import kotlinx.coroutines.test.runCurrent
import org.junit.Assert
/** Sets up shade state for tests for either value of the scene container flag. */
-class ShadeTestUtil constructor(val delegate: ShadeTestUtilDelegate) {
+class ShadeTestUtil(val delegate: ShadeTestUtilDelegate) {
/** Sets shade expansion to a value between 0-1. */
fun setShadeExpansion(shadeExpansion: Float) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt
index 1b50094ec0b7..a4631f17cb37 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt
@@ -16,57 +16,61 @@
package com.android.systemui.shade.domain.interactor
+import android.content.testableContext
import android.provider.Settings
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.fakeShadeRepository
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shared.settings.data.repository.secureSettingsRepository
-import kotlinx.coroutines.launch
+import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository
val Kosmos.shadeModeInteractor by Fixture {
ShadeModeInteractorImpl(
applicationScope = applicationCoroutineScope,
repository = shadeRepository,
- secureSettingsRepository = secureSettingsRepository,
+ secureSettingsRepository = fakeSecureSettingsRepository,
)
}
// TODO(b/391578667): Make this user-aware once supported by FakeSecureSettingsRepository.
/**
- * Enables the Dual Shade setting, and (optionally) sets the shade layout to be wide (`true`)
- * or narrow (`false`).
+ * Enables the Dual Shade setting, and (optionally) sets the shade layout to be wide (`true`) or
+ * narrow (`false`).
*
* In a wide layout, notifications and quick settings shades each take up only half the screen
* width. In a narrow layout, they each take up the entire screen width.
*/
fun Kosmos.enableDualShade(wideLayout: Boolean? = null) {
- testScope.launch {
- secureSettingsRepository.setInt(Settings.Secure.DUAL_SHADE, 1)
+ fakeSecureSettingsRepository.setBool(Settings.Secure.DUAL_SHADE, true)
- if (wideLayout != null) {
- fakeShadeRepository.setShadeLayoutWide(wideLayout)
- }
+ if (wideLayout != null) {
+ overrideLargeScreenResources(isLargeScreen = wideLayout)
+ fakeShadeRepository.setShadeLayoutWide(wideLayout)
}
}
// TODO(b/391578667): Make this user-aware once supported by FakeSecureSettingsRepository.
fun Kosmos.disableDualShade() {
- testScope.launch { secureSettingsRepository.setInt(Settings.Secure.DUAL_SHADE, 0) }
+ fakeSecureSettingsRepository.setBool(Settings.Secure.DUAL_SHADE, false)
}
fun Kosmos.enableSingleShade() {
- testScope.launch {
- disableDualShade()
- fakeShadeRepository.setShadeLayoutWide(false)
- }
+ disableDualShade()
+ overrideLargeScreenResources(isLargeScreen = false)
+ fakeShadeRepository.setShadeLayoutWide(false)
}
fun Kosmos.enableSplitShade() {
- testScope.launch {
- disableDualShade()
- fakeShadeRepository.setShadeLayoutWide(true)
+ disableDualShade()
+ overrideLargeScreenResources(isLargeScreen = true)
+ fakeShadeRepository.setShadeLayoutWide(true)
+}
+
+private fun Kosmos.overrideLargeScreenResources(isLargeScreen: Boolean) {
+ with(testableContext.orCreateTestableResources) {
+ addOverride(R.bool.config_use_split_notification_shade, isLargeScreen)
+ addOverride(R.bool.config_use_large_screen_shade_header, isLargeScreen)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt
index ca33a8663a51..f679fa4fafb6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel
import android.content.applicationContext
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.dump.dumpManager
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testDispatcher
@@ -31,6 +32,7 @@ val Kosmos.emptyShadeViewModel by
zenModeInteractor,
seenNotificationsInteractor,
notificationSettingsInteractor,
+ configurationInteractor,
testDispatcher,
dumpManager,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerKosmos.kt
new file mode 100644
index 000000000000..85e8fa5ec908
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerKosmos.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.stack
+
+import com.android.systemui.dump.dumpManager
+import com.android.systemui.haptics.msdl.msdlPlayer
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.notification.row.NotificationRowLogger
+import org.mockito.kotlin.mock
+
+var Kosmos.magneticNotificationRowManager: MagneticNotificationRowManager by
+ Kosmos.Fixture { magneticNotificationRowManagerImpl }
+
+val Kosmos.magneticNotificationRowManagerImpl by
+ Kosmos.Fixture {
+ MagneticNotificationRowManagerImpl(
+ msdlPlayer,
+ NotificationTargetsHelper(),
+ NotificationRoundnessManager(dumpManager),
+ mock<NotificationRowLogger>(),
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeZenModeController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeZenModeController.java
index 75df4e67db23..f239aed8f1b3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeZenModeController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeZenModeController.java
@@ -15,10 +15,8 @@
package com.android.systemui.utils.leaks;
import android.app.NotificationManager;
-import android.content.ComponentName;
import android.net.Uri;
import android.service.notification.ZenModeConfig;
-import android.service.notification.ZenModeConfig.ZenRule;
import android.testing.LeakCheck;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -40,11 +38,6 @@ public class FakeZenModeController extends BaseLeakChecker<Callback> implements
}
@Override
- public ZenRule getManualRule() {
- return null;
- }
-
- @Override
public ZenModeConfig getConfig() {
return null;
}
@@ -65,27 +58,7 @@ public class FakeZenModeController extends BaseLeakChecker<Callback> implements
}
@Override
- public ComponentName getEffectsSuppressor() {
- return null;
- }
-
- @Override
- public boolean isCountdownConditionSupported() {
- return false;
- }
-
- @Override
public int getCurrentUser() {
return 0;
}
-
- @Override
- public boolean isVolumeRestricted() {
- return false;
- }
-
- @Override
- public boolean areNotificationsHiddenInShade() {
- return false;
- }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt
index 151f3d45b906..9328216665de 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.window.domain.interactor
+import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
@@ -28,6 +29,7 @@ val Kosmos.windowRootViewBlurInteractor by
repository = windowRootViewBlurRepository,
keyguardInteractor = keyguardInteractor,
keyguardTransitionInteractor = keyguardTransitionInteractor,
+ communalInteractor = communalInteractor,
applicationScope = applicationCoroutineScope,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt
index 864048d51873..5a02bfbacd35 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.window.ui.viewmodel
import com.android.systemui.keyguard.ui.transitions.FakeBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.FakeGlanceableHubTransition
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
import org.mockito.internal.util.collections.Sets
@@ -26,5 +27,16 @@ val Kosmos.fakeBouncerTransitions by
Sets.newSet(FakeBouncerTransition(), FakeBouncerTransition())
}
+val Kosmos.fakeGlanceableHubTransitions by
+ Kosmos.Fixture<Set<FakeGlanceableHubTransition>> {
+ Sets.newSet(FakeGlanceableHubTransition(), FakeGlanceableHubTransition())
+ }
+
val Kosmos.windowRootViewModel by
- Kosmos.Fixture { WindowRootViewModel(fakeBouncerTransitions, windowRootViewBlurInteractor) }
+ Kosmos.Fixture {
+ WindowRootViewModel(
+ fakeBouncerTransitions,
+ fakeGlanceableHubTransitions,
+ windowRootViewBlurInteractor,
+ )
+ }
diff --git a/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java b/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java
index 81c7edf4adf1..b9dcc6160d68 100644
--- a/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java
+++ b/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java
@@ -32,8 +32,7 @@ import com.android.tools.r8.keepanno.annotations.UsedByReflection;
// Without this annotation, this class will be treated as unused class and be removed during build
// time.
@UsedByReflection(kind = KeepItemKind.CLASS_AND_METHODS)
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public final class ConnectivityServiceInitializerB extends SystemService {
private static final String TAG = ConnectivityServiceInitializerB.class.getSimpleName();
private final VcnManagementService mVcnManagementService;
diff --git a/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java b/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java
index c9a99d729e91..8edd63dc341f 100644
--- a/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java
+++ b/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java
@@ -165,8 +165,7 @@ import java.util.concurrent.TimeUnit;
* @hide
*/
// TODO(b/180451994): ensure all incoming + outgoing calls have a cleared calling identity
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
@NonNull private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java b/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java
index b04e25dff276..cedb2d16808f 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -79,8 +79,7 @@ import java.util.Set;
*
* @hide
*/
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class TelephonySubscriptionTracker extends BroadcastReceiver {
@NonNull private static final String TAG = TelephonySubscriptionTracker.class.getSimpleName();
private static final boolean LOG_DBG = false; // STOPSHIP if true
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java b/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java
index 97f86b1bff5b..0f8b2885cf4d 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java
@@ -77,8 +77,7 @@ import java.util.Set;
*
* @hide
*/
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class Vcn extends Handler {
private static final String TAG = Vcn.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java b/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java
index 300b80f942ef..da411174f95c 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java
@@ -174,8 +174,7 @@ import java.util.function.Consumer;
*
* @hide
*/
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class VcnGatewayConnection extends StateMachine {
private static final String TAG = VcnGatewayConnection.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java b/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java
index 38fcf09145d9..bc815eb27454 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java
@@ -58,8 +58,7 @@ import java.util.concurrent.Executor;
*/
// TODO(b/388919146): Implement a more generic solution to prevent concurrent modifications on
// mListeners and mRequests
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class VcnNetworkProvider extends NetworkProvider {
private static final String TAG = VcnNetworkProvider.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
index c8c645f1276d..aff7068b6c4f 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -61,8 +61,7 @@ import java.util.concurrent.TimeUnit;
*
* <p>This class is flag gated by "network_metric_monitor" and "ipsec_tramsform_state"
*/
-// TODO(b/374174952) Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class IpSecPacketLossDetector extends NetworkMetricMonitor {
private static final String TAG = IpSecPacketLossDetector.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
index 55829a5fe978..fc9c7ac8a335 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
@@ -44,8 +44,7 @@ import java.util.concurrent.Executor;
*
* <p>This class is flag gated by "network_metric_monitor"
*/
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public abstract class NetworkMetricMonitor implements AutoCloseable {
private static final String TAG = NetworkMetricMonitor.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
index 705141f3f1b4..7cb3257193a5 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -52,8 +52,7 @@ import java.util.Map;
import java.util.Set;
/** @hide */
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
class NetworkPriorityClassifier {
@NonNull private static final String TAG = NetworkPriorityClassifier.class.getSimpleName();
/**
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
index bc552e7e6afd..37ec0e8f40dc 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
@@ -75,8 +75,7 @@ import java.util.TreeSet;
*
* @hide
*/
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class UnderlyingNetworkController {
@NonNull private static final String TAG = UnderlyingNetworkController.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
index 776931bad73b..164b59f6f0cd 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
@@ -52,8 +52,7 @@ import java.util.concurrent.TimeUnit;
*
* @hide
*/
-// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
-@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@TargetApi(Build.VERSION_CODES.BAKLAVA)
public class UnderlyingNetworkEvaluator {
private static final String TAG = UnderlyingNetworkEvaluator.class.getSimpleName();
diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml
index c67e5db1601c..ae01f21b722c 100644
--- a/packages/VpnDialogs/res/values-in/strings.xml
+++ b/packages/VpnDialogs/res/values-in/strings.xml
@@ -30,7 +30,7 @@
<string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> disiapkan untuk selalu terhubung, tetapi saat ini tidak dapat terhubung. Anda akan terhubung jika VPN dapat terhubung ulang."</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Ubah setelan VPN"</string>
- <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string>
+ <string name="configure" msgid="4905518375574791375">"Konfigurasi"</string>
<string name="disconnect" msgid="971412338304200056">"Berhenti hubungkan"</string>
<string name="open_app" msgid="3717639178595958667">"Buka aplikasi"</string>
<string name="dismiss" msgid="6192859333764711227">"Tutup"</string>
diff --git a/ravenwood/scripts/add-annotations.sh b/ravenwood/scripts/add-annotations.sh
new file mode 100755
index 000000000000..3e86037d7c7b
--- /dev/null
+++ b/ravenwood/scripts/add-annotations.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# Copyright (C) 2025 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Use "ravehleper mm" to create a shell script which:
+# - Reads read a list of methods from STDIN
+# Which basically looks like a list of 'com.android.ravenwoodtest.tests.Test1#testA'
+# - Add @DisabledOnRavenwood to them
+#
+# Example usage:
+#
+# ./add-annotations.sh $ANDROID_BUILD_TOP/frameworks/base/ravenwood/tests <METHOD-LIST.txt
+#
+# Use a different annotation instead. (Note, in order to use an at, you need to use a double-at.)
+# ./add-annotations.sh -t '@@Ignore' $ANDROID_BUILD_TOP/frameworks/base/ravenwood/tests <METHOD-LIST.txt
+#
+
+set -e
+
+# Uncomment it to always build ravenhelper (slow)
+# ${BUILD_CMD:-m} ravenhelper
+
+# We add this line to each methods found.
+# Note, if we used a single @, that'd be handled as an at file. Use
+# the double-at instead.
+annotation="@@android.platform.test.annotations.DisabledOnRavenwood"
+while getopts "t:" opt; do
+case "$opt" in
+ t)
+ annotation="$OPTARG"
+ ;;
+ '?')
+ exit 1
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+source_dirs="$@"
+
+OUT_SCRIPT="${OUT_SCRIPT:-/tmp/add-annotations.sh}"
+
+rm -f "$OUT_SCRIPT"
+
+
+with_flag() {
+ local flag="$1"
+ shift
+
+ for arg in "$@"; do
+ echo "$flag $arg"
+ done
+}
+
+run() {
+ echo "Running: $*"
+ "$@"
+}
+
+run ${RAVENHELPER_CMD:-ravenhelper mm} \
+ --output-script $OUT_SCRIPT \
+ --text "$annotation" \
+ $(with_flag --src $source_dirs)
+
+
+if ! [[ -f $OUT_SCRIPT ]] ; then
+ # no operations generated.
+ exit 0
+fi
+
+echo
+echo "Created script at $OUT_SCRIPT. Run it with: sh $OUT_SCRIPT"
diff --git a/ravenwood/scripts/pta-framework.sh b/ravenwood/scripts/pta-framework.sh
index 46c2c01c8ee8..d396839ec182 100755
--- a/ravenwood/scripts/pta-framework.sh
+++ b/ravenwood/scripts/pta-framework.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright (C) 2024 The Android Open Source Project
+# Copyright (C) 2025 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index ae9276f711e1..297420d08ac1 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -354,6 +354,8 @@ class ArgIterator(
* Scan the arguments, and if any of them starts with an `@`, then load from the file
* and use its content as arguments.
*
+ * In order to pass an argument that starts with an '@', use '@@' instead.
+ *
* In this file, each line is treated as a single argument.
*
* The file can contain '#' as comments.
@@ -362,7 +364,10 @@ private fun expandAtFiles(args: Array<String>): List<String> {
val ret = mutableListOf<String>()
args.forEach { arg ->
- if (!arg.startsWith('@')) {
+ if (arg.startsWith("@@")) {
+ ret += arg.substring(1)
+ return@forEach
+ } else if (!arg.startsWith('@')) {
ret += arg
return@forEach
}
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt
index e6efbf6c5223..0be0c96c33d4 100644
--- a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt
@@ -27,6 +27,7 @@ import com.android.hoststubgen.executableName
import com.android.hoststubgen.log
import com.android.hoststubgen.runMainWithBoilerplate
import com.android.platform.test.ravenwood.ravenhelper.policytoannot.PtaProcessor
+import com.android.platform.test.ravenwood.ravenhelper.sourcemap.MarkMethodHandler
interface SubcommandHandler {
fun handle(args: List<String>)
@@ -39,7 +40,10 @@ fun usage() {
Subcommands:
pta: "policy-to-annotations" Convert policy file to annotations.
- (See the pta-framework.sh script for usage.) 1
+ (See the pta-framework.sh script for usage.)
+
+ mm: "mark methods" Used to add annotations (such as @DisabledOnRavenwood)
+ to methods.
""".trimIndent())
}
@@ -60,6 +64,7 @@ fun main(args: Array<String>) {
val subcommand = args[0]
val handler: SubcommandHandler = when (subcommand) {
"pta" -> PtaProcessor()
+ "mm" -> MarkMethodHandler()
else -> {
usage()
throw GeneralUserErrorException("Unknown subcommand '$subcommand'")
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt
index 3531ba951b1c..256d1234e1e6 100644
--- a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt
@@ -24,6 +24,8 @@ package com.android.platform.test.ravenwood.ravenhelper.policytoannot
import com.android.hoststubgen.log
import java.io.BufferedWriter
import java.io.File
+import java.io.FileOutputStream
+import java.io.OutputStreamWriter
enum class SourceOperationType {
/** Insert a line */
@@ -198,4 +200,26 @@ private fun toSedScript(ops: List<SourceOperation>, writer: BufferedWriter) {
}
}
}
+}
+
+fun createShellScript(ops: SourceOperations, scriptFile: String?): Boolean {
+ if (ops.size == 0) {
+ log.i("No files need to be updated.")
+ return false
+ }
+
+ val scriptWriter = BufferedWriter(
+ OutputStreamWriter(
+ scriptFile?.let { file ->
+ FileOutputStream(file)
+ } ?: System.out
+ ))
+
+ scriptWriter.use { writer ->
+ scriptFile?.let {
+ log.i("Creating script file at $it ...")
+ }
+ createShellScript(ops, writer)
+ }
+ return true
} \ No newline at end of file
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
index 5984e4fc8f9f..3657a9077577 100644
--- a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
@@ -31,10 +31,7 @@ import com.android.platform.test.ravenwood.ravenhelper.sourcemap.AllClassInfo
import com.android.platform.test.ravenwood.ravenhelper.sourcemap.ClassInfo
import com.android.platform.test.ravenwood.ravenhelper.sourcemap.MethodInfo
import com.android.platform.test.ravenwood.ravenhelper.sourcemap.SourceLoader
-import java.io.BufferedWriter
-import java.io.FileOutputStream
import java.io.FileReader
-import java.io.OutputStreamWriter
import java.util.regex.Pattern
/**
@@ -55,25 +52,7 @@ class PtaProcessor : SubcommandHandler {
)
converter.process()
- val ops = converter.resultOperations
-
- if (ops.size == 0) {
- log.i("No files need to be updated.")
- return
- }
-
- val scriptWriter = BufferedWriter(OutputStreamWriter(
- options.outputScriptFile.get?.let { file ->
- FileOutputStream(file)
- } ?: System.out
- ))
-
- scriptWriter.use { writer ->
- options.outputScriptFile.get?.let {
- log.i("Creating script file at $it ...")
- }
- createShellScript(ops, writer)
- }
+ createShellScript(converter.resultOperations, options.outputScriptFile.get)
}
}
@@ -424,7 +403,7 @@ private class TextPolicyToAnnotationConverter(
if (methodsAndAnnot == null) {
classHasMember = true
- return // This policy can't converted.
+ return // This policy can't be converted.
}
val methods = methodsAndAnnot.first
val annot = methodsAndAnnot.second
@@ -476,4 +455,4 @@ private class TextPolicyToAnnotationConverter(
classHasMember = true
}
}
-} \ No newline at end of file
+}
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MapOptions.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MapOptions.kt
new file mode 100644
index 000000000000..ee200bb39df2
--- /dev/null
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MapOptions.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.platform.test.ravenwood.ravenhelper.sourcemap
+
+import com.android.hoststubgen.ArgIterator
+import com.android.hoststubgen.ArgumentsException
+import com.android.hoststubgen.SetOnce
+import com.android.hoststubgen.ensureFileExists
+import com.android.hoststubgen.log
+
+/**
+ * Options for the "ravenhelper map" subcommand.
+ */
+class MapOptions(
+ /** Source files or directories. */
+ var sourceFilesOrDirectories: MutableList<String> = mutableListOf(),
+
+ /** Files containing target methods */
+ var targetMethodFiles: MutableList<String> = mutableListOf(),
+
+ /** Output script file. */
+ var outputScriptFile: SetOnce<String?> = SetOnce(null),
+
+ /** Text to insert. */
+ var text: SetOnce<String?> = SetOnce(null),
+) {
+ companion object {
+ fun parseArgs(args: List<String>): MapOptions {
+ val ret = MapOptions()
+ val ai = ArgIterator.withAtFiles(args.toTypedArray())
+
+ while (true) {
+ val arg = ai.nextArgOptional() ?: break
+
+ fun nextArg(): String = ai.nextArgRequired(arg)
+
+ if (log.maybeHandleCommandLineArg(arg) { nextArg() }) {
+ continue
+ }
+ try {
+ when (arg) {
+ // TODO: Write help
+ "-h", "--help" -> TODO("Help is not implemented yet")
+
+ "-s", "--src" ->
+ ret.sourceFilesOrDirectories.add(nextArg().ensureFileExists())
+
+ "-i", "--input" ->
+ ret.targetMethodFiles.add(nextArg().ensureFileExists())
+
+ "-o", "--output-script" ->
+ ret.outputScriptFile.set(nextArg())
+
+ "-t", "--text" ->
+ ret.text.set(nextArg())
+
+ else -> throw ArgumentsException("Unknown option: $arg")
+ }
+ } catch (e: SetOnce.SetMoreThanOnceException) {
+ throw ArgumentsException("Duplicate or conflicting argument found: $arg")
+ }
+ }
+
+ if (ret.sourceFilesOrDirectories.size == 0) {
+ throw ArgumentsException("Must specify at least one source path")
+ }
+
+ return ret
+ }
+ }
+
+ override fun toString(): String {
+ return """
+ PtaOptions{
+ sourceFilesOrDirectories=$sourceFilesOrDirectories
+ targetMethods=$targetMethodFiles
+ outputScriptFile=$outputScriptFile
+ text=$text
+ }
+ """.trimIndent()
+ }
+} \ No newline at end of file
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MarkMethodHandler.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MarkMethodHandler.kt
new file mode 100644
index 000000000000..8085253895f9
--- /dev/null
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/MarkMethodHandler.kt
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.platform.test.ravenwood.ravenhelper.sourcemap
+
+import com.android.hoststubgen.GeneralUserErrorException
+import com.android.hoststubgen.log
+import com.android.platform.test.ravenwood.ravenhelper.SubcommandHandler
+import com.android.platform.test.ravenwood.ravenhelper.policytoannot.SourceOperation
+import com.android.platform.test.ravenwood.ravenhelper.policytoannot.SourceOperationType
+import com.android.platform.test.ravenwood.ravenhelper.policytoannot.SourceOperations
+import com.android.platform.test.ravenwood.ravenhelper.policytoannot.createShellScript
+import com.android.platform.test.ravenwood.ravenhelper.psi.createUastEnvironment
+import java.io.BufferedReader
+import java.io.FileReader
+
+/**
+ * This is the main routine of the "mm" subcommands, which marks specified methods with
+ * a given line, which defaults to "@DisabledOnRavenwood". This can be used to add bulk-annotate
+ * tests methods that are failing.
+ *
+ * See the javadoc of [MarkMethodProcessor] for more details.
+ */
+class MarkMethodHandler : SubcommandHandler {
+ override fun handle(args: List<String>) {
+ val options = MapOptions.parseArgs(args)
+
+ log.i("Options: $options")
+
+ // Files from which we load a list of methods.
+ val inputFiles = if (options.targetMethodFiles.isEmpty()) {
+ log.w("[Reading method list from STDIN...]")
+ log.flush()
+ listOf("/dev/stdin")
+ } else {
+ options.targetMethodFiles
+ }
+
+ // A string to inject before each method.
+ val text = if (options.text.isSet) {
+ options.text.get!!
+ } else {
+ "@android.platform.test.annotations.DisabledOnRavenwood"
+ }
+
+ // Process.
+ val processor = MarkMethodProcessor(
+ options.sourceFilesOrDirectories,
+ inputFiles,
+ text,
+ )
+ processor.process()
+
+ // Create the output script.
+ createShellScript(processor.resultOperations, options.outputScriptFile.get)
+ }
+}
+
+/**
+ * Load a list of methods / classes from [targetMethodFiles], and inject [textToInsert] to
+ * each of them, to the source files under [sourceFilesOrDirectories]
+ *
+ * An example input files look like this -- this can be generated from atest output.
+ * <pre>
+
+ # We add @DisabledOnRavenwood to the following methods.
+ com.android.ravenwoodtest.tests.Test1#testA
+ com.android.ravenwoodtest.tests.Test1#testB
+ com.android.ravenwoodtest.tests.Test1#testC
+
+ # We add @DisabledOnRavenwood to the following class.
+ com.android.ravenwoodtest.tests.Test2
+
+ # Special case: we add the annotation to the class too.
+ com.android.ravenwoodtest.tests.Test3#initializationError
+ </pre>
+
+ */
+private class MarkMethodProcessor(
+ private val sourceFilesOrDirectories: List<String>,
+ private val targetMethodFiles: List<String>,
+ private val textToInsert: String,
+) {
+ private val classes = AllClassInfo()
+ val resultOperations = SourceOperations()
+
+ /**
+ * Entry point.
+ */
+ fun process() {
+ val env = createUastEnvironment()
+ try {
+ loadSources()
+
+ processInputFiles()
+ } finally {
+ env.dispose()
+ }
+ }
+
+ private fun loadSources() {
+ val env = createUastEnvironment()
+ try {
+ val loader = SourceLoader(env)
+ loader.load(sourceFilesOrDirectories, classes)
+ } finally {
+ env.dispose()
+ }
+ }
+
+ /**
+ * Process liput files. Input files looks like this:
+ * <pre>
+ * # We add @DisabledOnRavenwood to the following methods.
+ * com.android.ravenwoodtest.tests.Test1#testA
+ * com.android.ravenwoodtest.tests.Test1#testB
+ * com.android.ravenwoodtest.tests.Test1#testC
+ *
+ * # We add @DisabledOnRavenwood to the following class.
+ * com.android.ravenwoodtest.tests.Test2
+ *
+ * # Special case: we add the annotation to the class too.
+ * com.android.ravenwoodtest.tests.Test3#initializationError
+ * </pre>
+ */
+ private fun processInputFiles() {
+ targetMethodFiles.forEach { filename ->
+ BufferedReader(FileReader(filename)).use { reader ->
+ reader.readLines().forEach { line ->
+ if (line.isBlank() || line.startsWith('#')) {
+ return@forEach
+ }
+ processSingleLine(line)
+ }
+ }
+ }
+ }
+
+ private fun processSingleLine(line: String) {
+ val cm = line.split("#") // Class and method
+ if (cm.size > 2) {
+ throw GeneralUserErrorException("Input line \"$line\" contains too many #'s")
+ }
+ val className = cm[0]
+ val methodName = if (cm.size == 2 && cm[1] != "initializationError") {
+ cm[1]
+ } else {
+ ""
+ }
+
+ // Find class info
+ val ci = classes.findClass(className)
+ ?: throw GeneralUserErrorException("Class \"$className\" not found\"")
+
+ if (methodName == "") {
+ processClass(ci)
+ } else {
+ processMethod(ci, methodName)
+ }
+ }
+
+ private fun processClass(ci: ClassInfo) {
+ addOperation(ci.location, "Class ${ci.fullName}")
+ }
+
+ private fun processMethod(ci: ClassInfo, methodName: String) {
+ var methods = ci.methods[methodName]
+ ?: throw GeneralUserErrorException("method \"$methodName\" not found\"")
+ methods.forEach { mi ->
+ addOperation(mi.location, "Method ${mi.name}")
+ }
+ }
+
+ private fun addOperation(loc: Location, description: String) {
+ resultOperations.add(
+ SourceOperation(
+ loc.file,
+ loc.line,
+ SourceOperationType.Insert,
+ loc.getIndent() + textToInsert,
+ description
+ )
+ )
+ }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 91775f8eed96..8e0a7785c597 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -607,7 +607,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mLock,
mContext,
new MagnificationScaleProvider(mContext),
- Executors.newSingleThreadExecutor()
+ Executors.newSingleThreadExecutor(),
+ mContext.getMainLooper()
);
mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
mCaptioningManagerImpl = new CaptioningManagerImpl(mContext);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 75ec8ea88ace..486f1f449691 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -36,6 +36,8 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -53,6 +55,7 @@ import android.view.accessibility.MagnificationAnimationCallback;
import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.wm.WindowManagerInternal;
@@ -111,6 +114,20 @@ public class MagnificationController implements MagnificationConnectionManager.C
private final Executor mBackgroundExecutor;
+ private final Handler mHandler;
+ private @PanDirection int mActivePanDirection = PAN_DIRECTION_DOWN;
+ private int mActivePanDisplay = Display.INVALID_DISPLAY;
+ private boolean mRepeatKeysEnabled = true;
+
+ private @ZoomDirection int mActiveZoomDirection = ZOOM_DIRECTION_IN;
+ private int mActiveZoomDisplay = Display.INVALID_DISPLAY;
+
+ // TODO(b/355499907): Get initial repeat interval from repeat keys settings.
+ @VisibleForTesting
+ public static final int INITIAL_KEYBOARD_REPEAT_INTERVAL_MS = 500;
+ @VisibleForTesting
+ public static final int KEYBOARD_REPEAT_INTERVAL_MS = 60;
+
@GuardedBy("mLock")
private final SparseIntArray mCurrentMagnificationModeArray = new SparseIntArray();
@GuardedBy("mLock")
@@ -287,12 +304,13 @@ public class MagnificationController implements MagnificationConnectionManager.C
public MagnificationController(AccessibilityManagerService ams, Object lock,
Context context, MagnificationScaleProvider scaleProvider,
- Executor backgroundExecutor) {
+ Executor backgroundExecutor, Looper looper) {
mAms = ams;
mLock = lock;
mContext = context;
mScaleProvider = scaleProvider;
mBackgroundExecutor = backgroundExecutor;
+ mHandler = new Handler(looper);
LocalServices.getService(WindowManagerInternal.class)
.getAccessibilityController().setUiChangesForAccessibilityCallbacks(this);
mSupportWindowMagnification = context.getPackageManager().hasSystemFeature(
@@ -303,14 +321,20 @@ public class MagnificationController implements MagnificationConnectionManager.C
mAlwaysOnMagnificationFeatureFlag = new AlwaysOnMagnificationFeatureFlag(context);
mAlwaysOnMagnificationFeatureFlag.addOnChangedListener(
mBackgroundExecutor, mAms::updateAlwaysOnMagnification);
+
+ // TODO(b/355499907): Add an observer for repeat keys enabled changes,
+ // rather than initializing once at startup.
+ mRepeatKeysEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(), Settings.Secure.KEY_REPEAT_ENABLED, 1,
+ UserHandle.USER_CURRENT) != 0;
}
@VisibleForTesting
public MagnificationController(AccessibilityManagerService ams, Object lock,
Context context, FullScreenMagnificationController fullScreenMagnificationController,
MagnificationConnectionManager magnificationConnectionManager,
- MagnificationScaleProvider scaleProvider, Executor backgroundExecutor) {
- this(ams, lock, context, scaleProvider, backgroundExecutor);
+ MagnificationScaleProvider scaleProvider, Executor backgroundExecutor, Looper looper) {
+ this(ams, lock, context, scaleProvider, backgroundExecutor, looper);
mFullScreenMagnificationController = fullScreenMagnificationController;
mMagnificationConnectionManager = magnificationConnectionManager;
}
@@ -354,27 +378,60 @@ public class MagnificationController implements MagnificationConnectionManager.C
// pan diagonally) by decreasing diagonal movement by sqrt(2) to make it appear the same
// speed as non-diagonal movement.
panMagnificationByStep(displayId, direction);
+ mActivePanDirection = direction;
+ mActivePanDisplay = displayId;
+ if (mRepeatKeysEnabled) {
+ mHandler.sendMessageDelayed(
+ PooledLambda.obtainMessage(MagnificationController::maybeContinuePan, this),
+ INITIAL_KEYBOARD_REPEAT_INTERVAL_MS);
+ }
}
@Override
public void onPanMagnificationStop(int displayId,
@MagnificationController.PanDirection int direction) {
- // TODO(b/388847283): Handle held key gestures, which can be used
- // for continuous scaling and panning, until they are released.
-
+ if (direction == mActivePanDirection) {
+ mActivePanDisplay = Display.INVALID_DISPLAY;
+ }
}
@Override
public void onScaleMagnificationStart(int displayId,
@MagnificationController.ZoomDirection int direction) {
scaleMagnificationByStep(displayId, direction);
+ mActiveZoomDirection = direction;
+ mActiveZoomDisplay = displayId;
+ if (mRepeatKeysEnabled) {
+ mHandler.sendMessageDelayed(
+ PooledLambda.obtainMessage(MagnificationController::maybeContinueZoom, this),
+ INITIAL_KEYBOARD_REPEAT_INTERVAL_MS);
+ }
}
@Override
public void onScaleMagnificationStop(int displayId,
@MagnificationController.ZoomDirection int direction) {
- // TODO(b/388847283): Handle held key gestures, which can be used
- // for continuous scaling and panning, until they are released.
+ if (direction == mActiveZoomDirection) {
+ mActiveZoomDisplay = Display.INVALID_DISPLAY;
+ }
+ }
+
+ private void maybeContinuePan() {
+ if (mActivePanDisplay != Display.INVALID_DISPLAY) {
+ panMagnificationByStep(mActivePanDisplay, mActivePanDirection);
+ mHandler.sendMessageDelayed(
+ PooledLambda.obtainMessage(MagnificationController::maybeContinuePan, this),
+ KEYBOARD_REPEAT_INTERVAL_MS);
+ }
+ }
+
+ private void maybeContinueZoom() {
+ if (mActiveZoomDisplay != Display.INVALID_DISPLAY) {
+ scaleMagnificationByStep(mActiveZoomDisplay, mActiveZoomDirection);
+ mHandler.sendMessageDelayed(
+ PooledLambda.obtainMessage(MagnificationController::maybeContinueZoom, this),
+ KEYBOARD_REPEAT_INTERVAL_MS);
+ }
}
private void handleUserInteractionChanged(int displayId, int mode) {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 8ef44ad31021..aef1c081cf03 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1095,6 +1095,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
proto.write(WidgetProto.MAX_HEIGHT,
widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 0));
}
+ if (widget.views != null) {
+ proto.write(WidgetProto.VIEWS_BITMAP_MEMORY,
+ widget.views.estimateTotalBitmapMemoryUsage());
+ }
proto.end(token);
}
@@ -2846,7 +2850,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// For a full update we replace the RemoteViews completely.
widget.views = views;
}
- int memoryUsage;
+ long memoryUsage;
if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) &&
(widget.views != null) &&
((memoryUsage = widget.views.estimateMemoryUsage()) > mMaxWidgetBitmapMemory)) {
@@ -3503,6 +3507,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
if (widget.views != null) {
pw.print(" views="); pw.println(widget.views);
+ pw.print(" views_bitmap_memory=");
+ pw.println(widget.views.estimateTotalBitmapMemoryUsage());
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 25494fce9fbf..c68e54956c99 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -19,7 +19,6 @@ package com.android.server.autofill;
import static android.Manifest.permission.MANAGE_AUTO_FILL;
import static android.content.Context.AUTOFILL_MANAGER_SERVICE;
import static android.service.autofill.Flags.fixGetAutofillComponent;
-import static android.service.autofill.Flags.improveFillDialogAconfig;
import static android.view.autofill.AutofillManager.MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS;
import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
@@ -71,7 +70,6 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TimeUtils;
-import android.view.InsetsController;
import android.view.autofill.AutofillFeatureFlags;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
@@ -98,7 +96,6 @@ import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import com.android.server.infra.SecureSettingsServiceNameResolver;
-import com.android.server.wm.WindowManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -246,8 +243,6 @@ public final class AutofillManagerService
private static final boolean DEFAULT_PCC_USE_FALLBACK = true;
- private static final boolean DBG = false;
-
public AutofillManagerService(Context context) {
super(context,
new SecureSettingsServiceNameResolver(context, Settings.Secure.AUTOFILL_SERVICE),
@@ -306,79 +301,8 @@ public final class AutofillManagerService
mCredentialAutofillService = null;
Slog.w(TAG, "Invalid CredentialAutofillService");
}
-
- if (improveFillDialogAconfig()) {
- WindowManagerInternal windowManagerInternal = LocalServices.getService(
- WindowManagerInternal.class);
- WindowManagerInternal.ImeInsetsAnimationChangeListener
- imeInsetsAnimationChangeListener =
- new WindowManagerInternal.ImeInsetsAnimationChangeListener() {
- @Override
- public void onAnimationStart(
- @InsetsController.AnimationType int animationType, int userId) {
- if (DBG) {
- Slog.e(TAG,
- "onAnimationStart() notifyImeAnimationStart() "
- + "animationType:"
- + String.valueOf(animationType));
- }
- synchronized (mLock) {
-
- // We are mostly interested in animations that show up the IME
- if (animationType == InsetsController.ANIMATION_TYPE_HIDE) {
- // IME is going away
- mIsImeShowing = false;
- }
- if (animationType != InsetsController.ANIMATION_TYPE_SHOW) {
- return;
- }
- mIsImeShowing = true;
- mImeAnimatingWhileShowingUp = true;
- final AutofillManagerServiceImpl service =
- peekServiceForUserWithLocalBinderIdentityLocked(userId);
- if (service != null) {
- service.notifyImeAnimationStart();
- } else if (sVerbose) {
- Slog.v(TAG,
- "notifyImeAnimationStart(): no service for " + userId);
- }
- }
- }
-
- @Override
- public void onAnimationEnd(
- @InsetsController.AnimationType int animationType, int userId) {
- if (DBG) {
- Slog.e(TAG,
- "onAnimationEnd() notifyImeAnimationEnd() "
- + "animationType:"
- + String.valueOf(animationType));
- }
- // We are only interested in animations that show up the IME
- if (animationType != InsetsController.ANIMATION_TYPE_SHOW) {
- return;
- }
- mImeAnimatingWhileShowingUp = false;
- synchronized (mLock) {
- final AutofillManagerServiceImpl service =
- peekServiceForUserWithLocalBinderIdentityLocked(userId);
- if (service != null) {
- service.notifyImeAnimationEnd();
- } else if (sVerbose) {
- Slog.v(TAG, "notifyImeAnimationEnd(): no service for "
- + userId);
- }
- }
- }
- };
- windowManagerInternal.setImeInsetsAnimationChangeListener(
- imeInsetsAnimationChangeListener);
- }
}
- public boolean mImeAnimatingWhileShowingUp = false;
- public boolean mIsImeShowing = false;
-
@Override // from AbstractMasterSystemService
protected String getServiceSettingsProperty() {
return Settings.Secure.AUTOFILL_SERVICE;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index eda62334ff39..b39b5b1a7660 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -209,11 +209,6 @@ final class AutofillManagerServiceImpl
private final DisabledInfoCache mDisabledInfoCache;
- // Tracks active session id. There is no guarantee that such a session exists. For eg, if the
- // session is destroyed, the id may no longer be valid. We don't update the state in all the
- // cases.
- private int mActiveSessionId = NO_SESSION;
-
AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
AutofillCompatState autofillCompatState,
@@ -392,7 +387,6 @@ final class AutofillManagerServiceImpl
@NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback,
@NonNull ComponentName clientActivity, boolean compatMode,
boolean bindInstantServiceAllowed, int flags) {
- mActiveSessionId = NO_SESSION;
// FLAG_AUGMENTED_AUTOFILL_REQUEST is set in the flags when standard autofill is disabled
// but the package is allowlisted for augmented autofill
boolean forAugmentedAutofillOnly = (flags
@@ -451,7 +445,6 @@ final class AutofillManagerServiceImpl
if (newSession == null) {
return NO_SESSION;
}
- mActiveSessionId = newSession.id;
// Service can be null when it's only for augmented autofill
String servicePackageName = mInfo == null ? null : mInfo.getServiceInfo().packageName;
@@ -755,7 +748,6 @@ final class AutofillManagerServiceImpl
Slog.d(TAG, "restarting session " + sessionId + " due to manual request on "
+ autofillId);
}
- mActiveSessionId = sessionId;
return true;
}
if (sVerbose) {
@@ -765,8 +757,6 @@ final class AutofillManagerServiceImpl
return false;
}
-
- mActiveSessionId = sessionId;
session.updateLocked(autofillId, virtualBounds, value, action, flags);
return false;
}
@@ -886,54 +876,21 @@ final class AutofillManagerServiceImpl
}
@GuardedBy("mLock")
- public void notifyImeAnimationStart() {
- if (!isEnabledLocked()) {
- Slog.wtf(TAG, "Service not enabled");
- return;
- }
- final Session session = mSessions.get(mActiveSessionId);
- if (session == null) {
- Slog.v(TAG, "notifyImeAnimationEnd(): no session for " + mActiveSessionId);
- return;
- }
- session.notifyImeAnimationStart(SystemClock.elapsedRealtime());
- }
-
- @GuardedBy("mLock")
public void notifyImeAnimationEnd(int sessionId, long endTimeMs, int uid) {
if (!isEnabledLocked()) {
Slog.wtf(TAG, "Service not enabled");
return;
}
final Session session = mSessions.get(sessionId);
- if (session == null) {
+ if (session == null || uid != session.uid) {
Slog.v(TAG, "notifyImeAnimationEnd(): no session for "
+ sessionId + "(" + uid + ")");
return;
}
- if (uid != session.uid) {
- Slog.v(TAG, "notifyImeAnimationEnd(): Mismatched session id's "
- + sessionId + "(" + uid + ")");
- return;
- }
session.notifyImeAnimationEnd(endTimeMs);
}
@GuardedBy("mLock")
- public void notifyImeAnimationEnd() {
- if (!isEnabledLocked()) {
- Slog.wtf(TAG, "Service not enabled");
- return;
- }
- final Session session = mSessions.get(mActiveSessionId);
- if (session == null) {
- Slog.v(TAG, "notifyImeAnimationEnd(): no session for " + mActiveSessionId);
- return;
- }
- session.notifyImeAnimationEnd(SystemClock.elapsedRealtime());
- }
-
- @GuardedBy("mLock")
@Override // from PerUserSystemService
protected void handlePackageUpdateLocked(@NonNull String packageName) {
final ServiceInfo serviceInfo = mFieldClassificationStrategy.getServiceInfo();
diff --git a/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
index d8fbde4115d9..9a353fbc45bf 100644
--- a/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
+++ b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
@@ -76,7 +76,9 @@ public class BackupAgentConnectionManager {
@Nullable
private BackupAgentConnection mCurrentConnection;
+ @GuardedBy("mAgentConnectLock")
private final ArraySet<String> mRestoreNoRestrictedModePackages = new ArraySet<>();
+ @GuardedBy("mAgentConnectLock")
private final ArraySet<String> mBackupNoRestrictedModePackages = new ArraySet<>();
private final IActivityManager mActivityManager;
@@ -322,14 +324,16 @@ public class BackupAgentConnectionManager {
*/
public void setNoRestrictedModePackages(Set<String> packageNames,
@BackupAnnotations.OperationType int opType) {
- if (opType == BackupAnnotations.OperationType.BACKUP) {
- mBackupNoRestrictedModePackages.clear();
- mBackupNoRestrictedModePackages.addAll(packageNames);
- } else if (opType == BackupAnnotations.OperationType.RESTORE) {
- mRestoreNoRestrictedModePackages.clear();
- mRestoreNoRestrictedModePackages.addAll(packageNames);
- } else {
- throw new IllegalArgumentException("opType must be BACKUP or RESTORE");
+ synchronized (mAgentConnectLock) {
+ if (opType == BackupAnnotations.OperationType.BACKUP) {
+ mBackupNoRestrictedModePackages.clear();
+ mBackupNoRestrictedModePackages.addAll(packageNames);
+ } else if (opType == BackupAnnotations.OperationType.RESTORE) {
+ mRestoreNoRestrictedModePackages.clear();
+ mRestoreNoRestrictedModePackages.addAll(packageNames);
+ } else {
+ throw new IllegalArgumentException("opType must be BACKUP or RESTORE");
+ }
}
}
@@ -338,8 +342,10 @@ public class BackupAgentConnectionManager {
* restore.
*/
public void clearNoRestrictedModePackages() {
- mBackupNoRestrictedModePackages.clear();
- mRestoreNoRestrictedModePackages.clear();
+ synchronized (mAgentConnectLock) {
+ mBackupNoRestrictedModePackages.clear();
+ mRestoreNoRestrictedModePackages.clear();
+ }
}
/**
@@ -353,6 +359,7 @@ public class BackupAgentConnectionManager {
* {@link #mRestoreNoRestrictedModePackages} so this method will immediately return without
* any IPC to the transport.
*/
+ @GuardedBy("mAgentConnectLock")
private boolean shouldUseRestrictedBackupModeForPackage(
@BackupAnnotations.OperationType int mode, String packageName) {
// Key/Value apps are never put in restricted mode.
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index 2412b01ea8e2..3de84f17b583 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -79,6 +79,8 @@ final class DockObserver extends SystemService {
private final List<ExtconStateConfig> mExtconStateConfigs;
private DeviceProvisionedObserver mDeviceProvisionedObserver;
+ private final DockObserverLocalService mDockObserverLocalService;
+
static final class ExtconStateProvider {
private final Map<String, String> mState;
@@ -193,13 +195,21 @@ final class DockObserver extends SystemService {
} else {
Slog.i(TAG, "No extcon dock device found in this kernel.");
}
+
+ mDockObserverLocalService = new DockObserverLocalService();
+ LocalServices.addService(DockObserverInternal.class, mDockObserverLocalService);
+ }
+
+ public class DockObserverLocalService extends DockObserverInternal {
+ @Override
+ public int getActualDockState() {
+ return mActualDockState;
+ }
}
@Override
public void onStart() {
publishBinderService(TAG, new BinderService());
- // Logs dock state after setDockStateFromProviderLocked sets mReportedDockState
- FrameworkStatsLog.write(FrameworkStatsLog.DOCK_STATE_CHANGED, mReportedDockState);
}
@Override
@@ -230,6 +240,9 @@ final class DockObserver extends SystemService {
private void setDockStateLocked(int newState) {
if (newState != mReportedDockState) {
mReportedDockState = newState;
+ // Here is the place mReportedDockState is updated. Logs dock state for
+ // mReportedDockState here so we can report the dock state.
+ FrameworkStatsLog.write(FrameworkStatsLog.DOCK_STATE_CHANGED, mReportedDockState);
if (mSystemReady) {
// Wake up immediately when docked or undocked unless prohibited from doing so.
if (allowWakeFromDock()) {
diff --git a/services/core/java/com/android/server/DockObserverInternal.java b/services/core/java/com/android/server/DockObserverInternal.java
new file mode 100644
index 000000000000..ea41ffd86b65
--- /dev/null
+++ b/services/core/java/com/android/server/DockObserverInternal.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+/**
+ * @hide Only for use within the system server.
+ */
+public abstract class DockObserverInternal {
+ /** Retrieve the current dock state from DockObserver. */
+ public abstract int getActualDockState();
+}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 3abcd4e7a143..87f843b53a1d 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -440,6 +440,12 @@ public class OomAdjuster {
@GuardedBy("mService")
private long mNextFollowUpUpdateUptimeMs = NO_FOLLOW_UP_TIME;
+ /**
+ * The oom score a client needs to be to raise a service with UI out of cache.
+ */
+ private static final int CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD =
+ Flags.raiseBoundUiServiceThreshold() ? SERVICE_ADJ : PERCEPTIBLE_APP_ADJ;
+
@VisibleForTesting
public static class Injector {
boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -2878,15 +2884,12 @@ public class OomAdjuster {
}
}
if (adj > clientAdj) {
- // If this process has recently shown UI, and
- // the process that is binding to it is less
- // important than being visible, then we don't
- // care about the binding as much as we care
- // about letting this process get into the LRU
- // list to be killed and restarted if needed for
- // memory.
+ // If this process has recently shown UI, and the process that is binding to it
+ // is less important than a state that can be actively running, then we don't
+ // care about the binding as much as we care about letting this process get into
+ // the LRU list to be killed and restarted if needed for memory.
if (state.hasShownUi() && !state.getCachedIsHomeProcess()
- && clientAdj > PERCEPTIBLE_APP_ADJ) {
+ && clientAdj > CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD) {
if (adj >= CACHED_APP_MIN_ADJ) {
adjType = "cch-bound-ui-services";
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 3817ba1a28b9..2c0366e6a6db 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -24,11 +24,14 @@ import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
import static android.os.Process.ROOT_UID;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.window.flags.Flags.balClearAllowlistDuration;
import android.annotation.IntDef;
import android.annotation.Nullable;
@@ -305,6 +308,10 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
this.stringName = null;
}
+ @VisibleForTesting TempAllowListDuration getAllowlistDurationLocked(IBinder allowlistToken) {
+ return mAllowlistDuration.get(allowlistToken);
+ }
+
void setAllowBgActivityStarts(IBinder token, int flags) {
if (token == null) return;
if ((flags & FLAG_ACTIVITY_SENDER) != 0) {
@@ -323,6 +330,13 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
mAllowBgActivityStartsForActivitySender.remove(token);
mAllowBgActivityStartsForBroadcastSender.remove(token);
mAllowBgActivityStartsForServiceSender.remove(token);
+ if (mAllowlistDuration != null && balClearAllowlistDuration()) {
+ TempAllowListDuration duration = mAllowlistDuration.get(token);
+ if (duration != null
+ && duration.type == TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+ duration.type = TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
+ }
+ }
}
public void registerCancelListenerLocked(IResultReceiver receiver) {
@@ -703,7 +717,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
return res;
}
- private BackgroundStartPrivileges getBackgroundStartPrivilegesForActivitySender(
+ @VisibleForTesting BackgroundStartPrivileges getBackgroundStartPrivilegesForActivitySender(
IBinder allowlistToken) {
return mAllowBgActivityStartsForActivitySender.contains(allowlistToken)
? BackgroundStartPrivileges.allowBackgroundActivityStarts(allowlistToken)
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index d9be47193c89..e89889e794ba 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -308,3 +308,14 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "raise_bound_ui_service_threshold"
+ namespace: "backstage_power"
+ is_fixed_read_only: true
+ description: "Raise the threshold OomAdjuster will drop a service with UI to cached."
+ bug: "391691057"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 320dd8f188c0..5f118cb06d74 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -14744,6 +14744,7 @@ public class AudioService extends IAudioService.Stub
for (AudioMix mix : mMixes) {
mix.setVirtualDeviceId(mAttributionSource.getDeviceId());
}
+ mAudioSystem.registerPolicyMixes(mMixes, false);
return mAudioSystem.registerPolicyMixes(mMixes, true);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 2d802b21cf03..b6768c9c087a 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -38,7 +38,6 @@ import android.hardware.biometrics.AuthenticationStateListener;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.ComponentInfoInternal;
-import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IAuthService;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricService;
@@ -399,12 +398,6 @@ public class AuthService extends SystemService {
final long identity = Binder.clearCallingIdentity();
try {
- // We can't do this above because we need the READ_DEVICE_CONFIG permission, which
- // the calling user may not possess.
- if (!Flags.lastAuthenticationTime()) {
- throw new UnsupportedOperationException();
- }
-
return mBiometricService.getLastAuthenticationTime(userId, authenticators);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 290aab28a82d..6eade1cbf9bd 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -803,6 +803,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
error = BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED;
break;
+ case BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS:
+ error = BiometricConstants.BIOMETRIC_ERROR_CONTENT_VIEW_MORE_OPTIONS_BUTTON;
+ break;
default:
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 15b1f220bc3c..a5058dd51a33 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -44,7 +44,6 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricStateListener;
-import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IBiometricAuthenticator;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricSensorReceiver;
@@ -906,10 +905,6 @@ public class BiometricService extends SystemService {
int userId, @Authenticators.Types int authenticators) {
super.getLastAuthenticationTime_enforcePermission();
- if (!Flags.lastAuthenticationTime()) {
- throw new UnsupportedOperationException();
- }
-
Slogf.d(TAG, "getLastAuthenticationTime(userId=%d, authenticators=0x%x)",
userId, authenticators);
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index b9ce8c93dbde..373287d76442 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -245,6 +245,12 @@ public class DisplayManagerFlags {
Flags.FLAG_ENABLE_PLUGIN_MANAGER,
Flags::enablePluginManager
);
+
+ private final FlagState mEnableHdrOverridePluginTypeFlagState = new FlagState(
+ Flags.FLAG_ENABLE_HDR_OVERRIDE_PLUGIN_TYPE,
+ Flags::enableHdrOverridePluginType
+ );
+
private final FlagState mDisplayListenerPerformanceImprovementsFlagState = new FlagState(
Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS,
Flags::displayListenerPerformanceImprovements
@@ -550,6 +556,10 @@ public class DisplayManagerFlags {
return mEnablePluginManagerFlagState.isEnabled();
}
+ public boolean isHdrOverrideEnabled() {
+ return mEnableHdrOverridePluginTypeFlagState.isEnabled();
+ }
+
/**
* @return {@code true} if the flag for display listener performance improvements is enabled
*/
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 63cd2d73336a..bbd0e41e9af7 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -454,6 +454,14 @@ flag {
}
flag {
+ name: "enable_hdr_override_plugin_type"
+ namespace: "display_manager"
+ description: "Enable hdr override plugin type"
+ bug: "389873155"
+ is_fixed_read_only: true
+}
+
+flag {
name: "enable_display_content_mode_management"
namespace: "lse_desktop_experience"
description: "Enable switching the content mode of connected displays between mirroring and extened. Also change the default content mode to extended mode."
diff --git a/services/core/java/com/android/server/display/plugin/PluginManager.java b/services/core/java/com/android/server/display/plugin/PluginManager.java
index d4099975cafa..a8c4e7eaeb66 100644
--- a/services/core/java/com/android/server/display/plugin/PluginManager.java
+++ b/services/core/java/com/android/server/display/plugin/PluginManager.java
@@ -30,7 +30,9 @@ import dalvik.system.PathClassLoader;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Responsible for loading Plugins. Plugins and PluginSupplier are loaded from
@@ -43,7 +45,6 @@ public class PluginManager {
"com.android.server.display.plugin.PluginsProviderImpl";
private static final String TAG = "PluginManager";
- private final DisplayManagerFlags mFlags;
private final PluginStorage mPluginStorage;
private final List<Plugin> mPlugins;
@@ -53,10 +54,11 @@ public class PluginManager {
@VisibleForTesting
PluginManager(Context context, DisplayManagerFlags flags, Injector injector) {
- mFlags = flags;
- mPluginStorage = injector.getPluginStorage();
- if (mFlags.isPluginManagerEnabled()) {
- mPlugins = Collections.unmodifiableList(injector.loadPlugins(context, mPluginStorage));
+ Set<PluginType<?>> enabledTypes = injector.getEnabledPluginTypes(flags);
+ mPluginStorage = injector.getPluginStorage(enabledTypes);
+ if (flags.isPluginManagerEnabled()) {
+ mPlugins = Collections.unmodifiableList(injector.loadPlugins(
+ context, mPluginStorage, enabledTypes));
Slog.d(TAG, "loaded Plugins:" + mPlugins);
} else {
mPlugins = List.of();
@@ -74,15 +76,17 @@ public class PluginManager {
/**
* Adds change listener for particular plugin type
*/
- public <T> void subscribe(PluginType<T> type, PluginChangeListener<T> listener) {
- mPluginStorage.addListener(type, listener);
+ public <T> void subscribe(PluginType<T> type, String uniqueDisplayId,
+ PluginChangeListener<T> listener) {
+ mPluginStorage.addListener(type, uniqueDisplayId, listener);
}
/**
* Removes change listener
*/
- public <T> void unsubscribe(PluginType<T> type, PluginChangeListener<T> listener) {
- mPluginStorage.removeListener(type, listener);
+ public <T> void unsubscribe(PluginType<T> type, String uniqueDisplayId,
+ PluginChangeListener<T> listener) {
+ mPluginStorage.removeListener(type, uniqueDisplayId, listener);
}
/**
@@ -108,11 +112,21 @@ public class PluginManager {
}
static class Injector {
- PluginStorage getPluginStorage() {
- return new PluginStorage();
+
+ Set<PluginType<?>> getEnabledPluginTypes(DisplayManagerFlags flags) {
+ Set<PluginType<?>> enabledTypes = new HashSet<>();
+ if (flags.isHdrOverrideEnabled()) {
+ enabledTypes.add(PluginType.HDR_BOOST_OVERRIDE);
+ }
+ return enabledTypes;
+ }
+
+ PluginStorage getPluginStorage(Set<PluginType<?>> enabledTypes) {
+ return new PluginStorage(enabledTypes);
}
- List<Plugin> loadPlugins(Context context, PluginStorage storage) {
+ List<Plugin> loadPlugins(Context context, PluginStorage storage,
+ Set<PluginType<?>> enabledTypes) {
String providerJarPath = context
.getString(com.android.internal.R.string.config_pluginsProviderJarPath);
Slog.d(TAG, "loading plugins from:" + providerJarPath);
@@ -127,7 +141,7 @@ public class PluginManager {
Class<? extends PluginsProvider> cp = pathClassLoader.loadClass(PROVIDER_IMPL_CLASS)
.asSubclass(PluginsProvider.class);
PluginsProvider provider = cp.getDeclaredConstructor().newInstance();
- return provider.getPlugins(context, storage);
+ return provider.getPlugins(context, storage, enabledTypes);
} catch (ClassNotFoundException e) {
Slog.e(TAG, "loading failed: " + PROVIDER_IMPL_CLASS + " is not found in"
+ providerJarPath, e);
diff --git a/services/core/java/com/android/server/display/plugin/PluginStorage.java b/services/core/java/com/android/server/display/plugin/PluginStorage.java
index dd3415fb614d..d17fbe21deeb 100644
--- a/services/core/java/com/android/server/display/plugin/PluginStorage.java
+++ b/services/core/java/com/android/server/display/plugin/PluginStorage.java
@@ -20,10 +20,14 @@ import android.annotation.Nullable;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import java.io.PrintWriter;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -35,42 +39,111 @@ import java.util.Set;
public class PluginStorage {
private static final String TAG = "PluginStorage";
+ // Special ID used to indicate that given value is to be applied globally, rather than to a
+ // specific display. If both GLOBAL and specific display values are present - specific display
+ // value is selected.
+ @VisibleForTesting
+ static final String GLOBAL_ID = "GLOBAL";
+
private final Object mLock = new Object();
@GuardedBy("mLock")
- private final Map<PluginType<?>, Object> mValues = new HashMap<>();
+ private final Map<PluginType<?>, ValuesContainer<?>> mValues = new HashMap<>();
@GuardedBy("mLock")
private final Map<PluginType<?>, ListenersContainer<?>> mListeners = new HashMap<>();
@GuardedBy("mLock")
- private final PluginEventStorage mPluginEventStorage = new PluginEventStorage();
+ private final Map<String, PluginEventStorage> mPluginEventStorages = new HashMap<>();
/**
- * Updates value in storage and forwards it to corresponding listeners.
- * Should be called by OEM Plugin implementation in order to provide communicate with Framework
+ * Updates value in storage and forwards it to corresponding listeners for all displays
+ * that does not have display specific value.
+ * Should be called by OEM Plugin implementation in order to communicate with Framework
*/
@KeepForApi
- public <T> void updateValue(PluginType<T> type, @Nullable T value) {
- Slog.d(TAG, "updateValue, type=" + type.mName + "; value=" + value);
+ public <T> void updateGlobalValue(PluginType<T> type, @Nullable T value) {
+ updateValue(type, GLOBAL_ID, value);
+ }
+
+ private final Set<PluginType<?>> mEnabledTypes;
+
+ PluginStorage(Set<PluginType<?>> enabledTypes) {
+ mEnabledTypes = Collections.unmodifiableSet(enabledTypes);
+ }
+
+ /**
+ * Updates value in storage and forwards it to corresponding listeners for specific display.
+ * Should be called by OEM Plugin implementation in order to communicate with Framework
+ * @param type - plugin type, that need to be updated
+ * @param uniqueDisplayId - uniqueDisplayId that this type/value should be applied to
+ * @param value - plugin value for particular type and display
+ */
+ @KeepForApi
+ public <T> void updateValue(PluginType<T> type, String uniqueDisplayId, @Nullable T value) {
+ if (isTypeDisabled(type)) {
+ Slog.d(TAG, "updateValue ignored for disabled type=" + type.mName);
+ return;
+ }
+ Slog.d(TAG, "updateValue, type=" + type.mName + "; value=" + value
+ + "; displayId=" + uniqueDisplayId);
Set<PluginManager.PluginChangeListener<T>> localListeners;
+ T valueToNotify;
synchronized (mLock) {
- mValues.put(type, value);
- mPluginEventStorage.onValueUpdated(type);
- ListenersContainer<T> container = getListenersContainerForTypeLocked(type);
- localListeners = new LinkedHashSet<>(container.mListeners);
+ ValuesContainer<T> valuesByType = getValuesContainerLocked(type);
+ valuesByType.updateValueLocked(uniqueDisplayId, value);
+ // if value was set to null, we might need to notify with GLOBAL value instead
+ valueToNotify = valuesByType.getValueLocked(uniqueDisplayId);
+
+ PluginEventStorage storage = mPluginEventStorages.computeIfAbsent(uniqueDisplayId,
+ d -> new PluginEventStorage());
+ storage.onValueUpdated(type);
+
+ localListeners = getListenersForUpdateLocked(type, uniqueDisplayId);
}
Slog.d(TAG, "updateValue, notifying listeners=" + localListeners);
- localListeners.forEach(l -> l.onChanged(value));
+ localListeners.forEach(l -> l.onChanged(valueToNotify));
+ }
+
+ @GuardedBy("mLock")
+ private <T> Set<PluginManager.PluginChangeListener<T>> getListenersForUpdateLocked(
+ PluginType<T> type, String uniqueDisplayId) {
+ ListenersContainer<T> listenersContainer = getListenersContainerLocked(type);
+ Set<PluginManager.PluginChangeListener<T>> localListeners = new LinkedHashSet<>();
+ // if GLOBAL value change we need to notify only listeners for displays that does not
+ // have display specific value
+ if (GLOBAL_ID.equals(uniqueDisplayId)) {
+ ValuesContainer<T> valuesContainer = getValuesContainerLocked(type);
+ Set<String> excludedDisplayIds = valuesContainer.getNonGlobalDisplaysLocked();
+ listenersContainer.mListeners.forEach((localDisplayId, listeners) -> {
+ if (!excludedDisplayIds.contains(localDisplayId)) {
+ localListeners.addAll(listeners);
+ }
+ });
+ } else {
+ localListeners.addAll(
+ listenersContainer.mListeners.getOrDefault(uniqueDisplayId, Set.of()));
+ }
+ return localListeners;
}
/**
* Adds listener for PluginType. If storage already has value for this type, listener will
* be notified immediately.
*/
- <T> void addListener(PluginType<T> type, PluginManager.PluginChangeListener<T> listener) {
+ <T> void addListener(PluginType<T> type, String uniqueDisplayId,
+ PluginManager.PluginChangeListener<T> listener) {
+ if (isTypeDisabled(type)) {
+ Slog.d(TAG, "addListener ignored for disabled type=" + type.mName);
+ return;
+ }
+ if (GLOBAL_ID.equals(uniqueDisplayId)) {
+ Slog.d(TAG, "addListener ignored for GLOBAL_ID, type=" + type.mName);
+ return;
+ }
T value = null;
synchronized (mLock) {
- ListenersContainer<T> container = getListenersContainerForTypeLocked(type);
- if (container.mListeners.add(listener)) {
- value = getValueForTypeLocked(type);
+ ListenersContainer<T> container = getListenersContainerLocked(type);
+ if (container.addListenerLocked(uniqueDisplayId, listener)) {
+ ValuesContainer<T> valuesContainer = getValuesContainerLocked(type);
+ value = valuesContainer.getValueLocked(uniqueDisplayId);
}
}
if (value != null) {
@@ -81,10 +154,19 @@ public class PluginStorage {
/**
* Removes listener
*/
- <T> void removeListener(PluginType<T> type, PluginManager.PluginChangeListener<T> listener) {
+ <T> void removeListener(PluginType<T> type, String uniqueDisplayId,
+ PluginManager.PluginChangeListener<T> listener) {
+ if (isTypeDisabled(type)) {
+ Slog.d(TAG, "removeListener ignored for disabled type=" + type.mName);
+ return;
+ }
+ if (GLOBAL_ID.equals(uniqueDisplayId)) {
+ Slog.d(TAG, "removeListener ignored for GLOBAL_ID, type=" + type.mName);
+ return;
+ }
synchronized (mLock) {
- ListenersContainer<T> container = getListenersContainerForTypeLocked(type);
- container.mListeners.remove(listener);
+ ListenersContainer<T> container = getListenersContainerLocked(type);
+ container.removeListenerLocked(uniqueDisplayId, listener);
}
}
@@ -92,42 +174,41 @@ public class PluginStorage {
* Print the object's state and debug information into the given stream.
*/
void dump(PrintWriter pw) {
- Map<PluginType<?>, Object> localValues;
+ Map<PluginType<?>, Map<String, Object>> localValues = new HashMap<>();
@SuppressWarnings("rawtypes")
- Map<PluginType, Set> localListeners = new HashMap<>();
- List<PluginEventStorage.TimeFrame> timeFrames;
+ Map<PluginType, Map<String, Set>> localListeners = new HashMap<>();
+ Map<String, List<PluginEventStorage.TimeFrame>> timeFrames = new HashMap<>();
synchronized (mLock) {
- timeFrames = mPluginEventStorage.getTimeFrames();
- localValues = new HashMap<>(mValues);
- mListeners.forEach((type, container) -> localListeners.put(type, container.mListeners));
+ mPluginEventStorages.forEach((displayId, storage) -> {
+ timeFrames.put(displayId, storage.getTimeFrames());
+ });
+ mValues.forEach((type, valueContainer) -> {
+ localValues.put(type, new HashMap<>(valueContainer.mValues));
+ });
+ mListeners.forEach((type, container) -> {
+ localListeners.put(type, new HashMap<>(container.mListeners));
+ });
}
pw.println("PluginStorage:");
pw.println("values=" + localValues);
pw.println("listeners=" + localListeners);
pw.println("PluginEventStorage:");
- for (PluginEventStorage.TimeFrame timeFrame: timeFrames) {
- timeFrame.dump(pw);
+ for (Map.Entry<String, List<PluginEventStorage.TimeFrame>> timeFrameEntry :
+ timeFrames.entrySet()) {
+ pw.println("TimeFrames for displayId=" + timeFrameEntry.getKey());
+ for (PluginEventStorage.TimeFrame timeFrame : timeFrameEntry.getValue()) {
+ timeFrame.dump(pw);
+ }
}
}
- @GuardedBy("mLock")
- @SuppressWarnings("unchecked")
- private <T> T getValueForTypeLocked(PluginType<T> type) {
- Object value = mValues.get(type);
- if (value == null) {
- return null;
- } else if (type.mType == value.getClass()) {
- return (T) value;
- } else {
- Slog.d(TAG, "getValueForType: unexpected value type=" + value.getClass().getName()
- + ", expected=" + type.mType.getName());
- return null;
- }
+ private boolean isTypeDisabled(PluginType<?> type) {
+ return !mEnabledTypes.contains(type);
}
@GuardedBy("mLock")
@SuppressWarnings("unchecked")
- private <T> ListenersContainer<T> getListenersContainerForTypeLocked(PluginType<T> type) {
+ private <T> ListenersContainer<T> getListenersContainerLocked(PluginType<T> type) {
ListenersContainer<?> container = mListeners.get(type);
if (container == null) {
ListenersContainer<T> lc = new ListenersContainer<>();
@@ -138,7 +219,65 @@ public class PluginStorage {
}
}
+ @GuardedBy("mLock")
+ @SuppressWarnings("unchecked")
+ private <T> ValuesContainer<T> getValuesContainerLocked(PluginType<T> type) {
+ ValuesContainer<?> container = mValues.get(type);
+ if (container == null) {
+ ValuesContainer<T> vc = new ValuesContainer<>();
+ mValues.put(type, vc);
+ return vc;
+ } else {
+ return (ValuesContainer<T>) container;
+ }
+ }
+
private static final class ListenersContainer<T> {
- private final Set<PluginManager.PluginChangeListener<T>> mListeners = new LinkedHashSet<>();
+ private final Map<String, Set<PluginManager.PluginChangeListener<T>>> mListeners =
+ new LinkedHashMap<>();
+
+ private boolean addListenerLocked(
+ String uniqueDisplayId, PluginManager.PluginChangeListener<T> listener) {
+ Set<PluginManager.PluginChangeListener<T>> listenersForDisplay =
+ mListeners.computeIfAbsent(uniqueDisplayId, k -> new LinkedHashSet<>());
+ return listenersForDisplay.add(listener);
+ }
+
+ private void removeListenerLocked(String uniqueDisplayId,
+ PluginManager.PluginChangeListener<T> listener) {
+ Set<PluginManager.PluginChangeListener<T>> listenersForDisplay = mListeners.get(
+ uniqueDisplayId);
+ if (listenersForDisplay == null) {
+ return;
+ }
+
+ listenersForDisplay.remove(listener);
+
+ if (listenersForDisplay.isEmpty()) {
+ mListeners.remove(uniqueDisplayId);
+ }
+ }
+ }
+
+ private static final class ValuesContainer<T> {
+ private final Map<String, T> mValues = new HashMap<>();
+
+ private void updateValueLocked(String uniqueDisplayId, @Nullable T value) {
+ if (value == null) {
+ mValues.remove(uniqueDisplayId);
+ } else {
+ mValues.put(uniqueDisplayId, value);
+ }
+ }
+
+ private Set<String> getNonGlobalDisplaysLocked() {
+ Set<String> keys = new HashSet<>(mValues.keySet());
+ keys.remove(GLOBAL_ID);
+ return keys;
+ }
+
+ private @Nullable T getValueLocked(String displayId) {
+ return mValues.getOrDefault(displayId, mValues.get(GLOBAL_ID));
+ }
}
}
diff --git a/services/core/java/com/android/server/display/plugin/PluginType.java b/services/core/java/com/android/server/display/plugin/PluginType.java
index fb60833d259e..e4d2f854ea48 100644
--- a/services/core/java/com/android/server/display/plugin/PluginType.java
+++ b/services/core/java/com/android/server/display/plugin/PluginType.java
@@ -18,6 +18,7 @@ package com.android.server.display.plugin;
import com.android.internal.annotations.Keep;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.plugin.types.HdrBoostOverride;
/**
* Represent customisation entry point to Framework. OEM and Framework team should define
@@ -28,6 +29,15 @@ import com.android.internal.annotations.VisibleForTesting;
*/
@Keep
public class PluginType<T> {
+ /*
+ * PluginType for HDR boost override. If set, system will use overridden value instead
+ * system default parameters. To switch back to default system behaviour, Plugin should set
+ * this type value to null.
+ * Value change will trigger whole power state recalculation, so plugins should not update
+ * value for this type too often.
+ */
+ public static final PluginType<HdrBoostOverride> HDR_BOOST_OVERRIDE = new PluginType<>(
+ HdrBoostOverride.class, "hdr_boost_override");
final Class<T> mType;
final String mName;
diff --git a/services/core/java/com/android/server/display/plugin/PluginsProvider.java b/services/core/java/com/android/server/display/plugin/PluginsProvider.java
index 9ad85f67bc8b..ec74c860ca58 100644
--- a/services/core/java/com/android/server/display/plugin/PluginsProvider.java
+++ b/services/core/java/com/android/server/display/plugin/PluginsProvider.java
@@ -22,6 +22,7 @@ import android.content.Context;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import java.util.List;
+import java.util.Set;
/**
* Interface that OEMs should implement in order to supply Plugins to PluginManager
@@ -32,5 +33,6 @@ public interface PluginsProvider {
* Provides list of Plugins to PluginManager
*/
@NonNull
- List<Plugin> getPlugins(Context context, PluginStorage storage);
+ List<Plugin> getPlugins(
+ Context context, PluginStorage storage, Set<PluginType<?>> enabledTypes);
}
diff --git a/services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java b/services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java
new file mode 100644
index 000000000000..22e024da5f52
--- /dev/null
+++ b/services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.plugin.types;
+
+import android.annotation.FloatRange;
+import android.os.PowerManager;
+
+import com.android.server.display.DisplayBrightnessState;
+
+/**
+ * HDR boost override value.
+ * @param sdrHdrRatio - HDR to SDR multiplier, if < 1 HDR boost is off.
+ * @param maxHdrBrightness - Brightness max when boosted. Value in range from BRIGHTNESS_MIN to
+ * BRIGHTNESS_MAX. If not used should be set to PowerManager.BRIGHTNESS_MAX
+ * @param customTransitionRate - Custom transition rate for transitioning to new HDR brightness.
+ * If not used should be set to
+ * DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET
+ */
+public record HdrBoostOverride(
+ @FloatRange(from = 0)
+ float sdrHdrRatio,
+ @FloatRange(from = PowerManager.BRIGHTNESS_MIN, to = PowerManager.BRIGHTNESS_MAX)
+ float maxHdrBrightness,
+ float customTransitionRate) {
+ /**
+ * Constant for HDR boost off. Plugins should use this constant instead of creating new objects
+ */
+ private static final HdrBoostOverride HDR_OFF = new HdrBoostOverride(0,
+ PowerManager.BRIGHTNESS_MAX, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET);
+
+ /**
+ * Create HdrBoostOverride for HDR boost off
+ */
+ public static HdrBoostOverride forHdrOff() {
+ return HDR_OFF;
+ }
+
+ /**
+ * Create HdrBoostOverride for sdr-hdr ration override
+ */
+ public static HdrBoostOverride forSdrHdrRatio(float sdrHdrRatio) {
+ return new HdrBoostOverride(sdrHdrRatio,
+ PowerManager.BRIGHTNESS_MAX, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET);
+ }
+}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index e28939bc1fbd..6e5e0fd5224f 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -25,6 +25,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
+import android.credentials.flags.Flags;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
@@ -1173,8 +1174,19 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
final String[] serviceNames = mServiceNameResolver.getDefaultServiceNameList(
userId);
if (serviceNames != null) {
+ if (Flags.packageUpdateFixEnabled()) {
+ if (mServiceNameResolver.isConfiguredInMultipleMode()) {
+ // Remove any service that is in the cache but is no longer valid
+ // after this modification for this particular package
+ removeInvalidCachedServicesLocked(serviceNames, packageName,
+ userId);
+ }
+ }
+
+ // Update services that are still valid
for (int i = 0; i < serviceNames.length; i++) {
- peekAndUpdateCachedServiceLocked(packageName, userId, serviceNames[i]);
+ peekAndUpdateCachedServiceLocked(packageName, userId,
+ serviceNames[i]);
}
}
}
@@ -1231,6 +1243,36 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
}
@GuardedBy("mLock")
+ @SuppressWarnings("GuardedBy") // ErrorProne requires this.mLock for
+ // handleServiceRemovedMultiModeLocked which is the same
+ private void removeInvalidCachedServicesLocked(String[] validServices,
+ String packageName, int userId) {
+ visitServicesLocked((s) -> {
+ ComponentName serviceComponentName = s
+ .getServiceComponentName();
+ if (serviceComponentName != null && serviceComponentName
+ .getPackageName().equals(packageName)) {
+ if (!serviceInValidServiceList(serviceComponentName,
+ validServices)) {
+ handleServiceRemovedMultiModeLocked(
+ serviceComponentName, userId);
+ }
+ }
+ });
+ }
+
+ private boolean serviceInValidServiceList(ComponentName serviceComponentName,
+ String[] serviceNames) {
+ for (String service: serviceNames) {
+ ComponentName componentName = ComponentName.unflattenFromString(service);
+ if (componentName != null && componentName.equals(serviceComponentName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @GuardedBy("mLock")
@SuppressWarnings("unused")
protected void onServicePackageDataClearedMultiModeLocked(String packageName, int userId) {
if (verbose) {
@@ -1246,6 +1288,12 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
}
@GuardedBy("mLock")
+ protected void handleServiceRemovedMultiModeLocked(ComponentName serviceComponentName,
+ int userId) {
+ if (verbose) Slog.v(mTag, "handleServiceRemovedMultiModeLocked(" + userId + ")");
+ }
+
+ @GuardedBy("mLock")
protected void removeServiceFromCache(@NonNull S service, int userId) {
if (mServicesCacheList.get(userId) != null) {
mServicesCacheList.get(userId).remove(service);
diff --git a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
index af025c0ef4da..81d3e0c56e14 100644
--- a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
@@ -323,7 +323,7 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
* if the service is disabled.
*/
@Nullable
- public final ComponentName getServiceComponentName() {
+ public ComponentName getServiceComponentName() {
synchronized (mLock) {
return mServiceInfo == null ? null : mServiceInfo.getComponentName();
}
diff --git a/services/core/java/com/android/server/infra/OWNERS b/services/core/java/com/android/server/infra/OWNERS
index 4fea05d295b6..0f0d382e28f8 100644
--- a/services/core/java/com/android/server/infra/OWNERS
+++ b/services/core/java/com/android/server/infra/OWNERS
@@ -1,3 +1,4 @@
# Bug component: 655446
srazdan@google.com
+reemabajwa@google.com
diff --git a/services/core/java/com/android/server/input/InputGestureManager.java b/services/core/java/com/android/server/input/InputGestureManager.java
index 32b36bfb50e5..108afba7c52a 100644
--- a/services/core/java/com/android/server/input/InputGestureManager.java
+++ b/services/core/java/com/android/server/input/InputGestureManager.java
@@ -152,7 +152,7 @@ final class InputGestureManager {
),
createKeyGesture(
KeyEvent.KEYCODE_S,
- KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON,
+ KeyEvent.META_META_ON,
KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT
),
createKeyGesture(
diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java
index 4e5c720f9f1c..d2486fe8bd66 100644
--- a/services/core/java/com/android/server/input/InputManagerInternal.java
+++ b/services/core/java/com/android/server/input/InputManagerInternal.java
@@ -20,7 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.graphics.PointF;
-import android.hardware.display.DisplayTopology;
+import android.hardware.display.DisplayTopologyGraph;
import android.hardware.display.DisplayViewport;
import android.hardware.input.KeyGestureEvent;
import android.os.IBinder;
@@ -51,7 +51,7 @@ public abstract class InputManagerInternal {
* Called by {@link com.android.server.display.DisplayManagerService} to inform InputManager
* about changes in the displays topology.
*/
- public abstract void setDisplayTopology(DisplayTopology topology);
+ public abstract void setDisplayTopology(DisplayTopologyGraph topology);
/**
* Called by the power manager to tell the input manager whether it should start
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 2ba35d6a70d2..af021e5f515b 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -52,7 +52,7 @@ import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager.Sensors;
import android.hardware.SensorPrivacyManagerInternal;
import android.hardware.display.DisplayManagerInternal;
-import android.hardware.display.DisplayTopology;
+import android.hardware.display.DisplayTopologyGraph;
import android.hardware.display.DisplayViewport;
import android.hardware.input.AidlInputGestureData;
import android.hardware.input.HostUsiVersion;
@@ -662,8 +662,8 @@ public class InputManagerService extends IInputManager.Stub
mNative.setPointerDisplayId(mWindowManagerCallbacks.getPointerDisplayId());
}
- private void setDisplayTopologyInternal(DisplayTopology topology) {
- mNative.setDisplayTopology(topology.getGraph());
+ private void setDisplayTopologyInternal(DisplayTopologyGraph topology) {
+ mNative.setDisplayTopology(topology);
}
/**
@@ -1261,6 +1261,15 @@ public class InputManagerService extends IInputManager.Stub
@EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
@Override // Binder call
+ public void setKeyboardLayoutOverrideForInputDevice(InputDeviceIdentifier identifier,
+ String keyboardLayoutDescriptor) {
+ super.setKeyboardLayoutOverrideForInputDevice_enforcePermission();
+ mKeyboardLayoutManager.setKeyboardLayoutOverrideForInputDevice(identifier,
+ keyboardLayoutDescriptor);
+ }
+
+ @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
+ @Override // Binder call
public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@Nullable InputMethodSubtype imeSubtype, String keyboardLayoutDescriptor) {
@@ -3524,7 +3533,7 @@ public class InputManagerService extends IInputManager.Stub
}
@Override
- public void setDisplayTopology(DisplayTopology topology) {
+ public void setDisplayTopology(DisplayTopologyGraph topology) {
setDisplayTopologyInternal(topology);
}
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 1d1a178ff20b..b8ce86b7c98c 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -113,6 +113,7 @@ class KeyboardLayoutManager implements InputManager.InputDeviceListener {
private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 2;
private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 3;
+ private static final String GLOBAL_OVERRIDE_KEY = "GLOBAL_OVERRIDE_KEY";
private final Context mContext;
private final NativeInputManagerService mNative;
@@ -508,26 +509,44 @@ class KeyboardLayoutManager implements InputManager.InputDeviceListener {
}
@AnyThread
+ public void setKeyboardLayoutOverrideForInputDevice(InputDeviceIdentifier identifier,
+ String keyboardLayoutDescriptor) {
+ InputDevice inputDevice = getInputDevice(identifier);
+ if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
+ return;
+ }
+ KeyboardIdentifier keyboardIdentifier = new KeyboardIdentifier(inputDevice);
+ setKeyboardLayoutForInputDeviceInternal(keyboardIdentifier, GLOBAL_OVERRIDE_KEY,
+ keyboardLayoutDescriptor);
+ }
+
+ @AnyThread
public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@Nullable InputMethodSubtype imeSubtype,
String keyboardLayoutDescriptor) {
- Objects.requireNonNull(keyboardLayoutDescriptor,
- "keyboardLayoutDescriptor must not be null");
InputDevice inputDevice = getInputDevice(identifier);
if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
return;
}
KeyboardIdentifier keyboardIdentifier = new KeyboardIdentifier(inputDevice);
- String layoutKey = new LayoutKey(keyboardIdentifier,
+ final String datastoreKey = new LayoutKey(keyboardIdentifier,
new ImeInfo(userId, imeInfo, imeSubtype)).toString();
+ setKeyboardLayoutForInputDeviceInternal(keyboardIdentifier, datastoreKey,
+ keyboardLayoutDescriptor);
+ }
+
+ private void setKeyboardLayoutForInputDeviceInternal(KeyboardIdentifier identifier,
+ String datastoreKey, String keyboardLayoutDescriptor) {
+ Objects.requireNonNull(keyboardLayoutDescriptor,
+ "keyboardLayoutDescriptor must not be null");
synchronized (mDataStore) {
try {
- if (mDataStore.setKeyboardLayout(keyboardIdentifier.toString(), layoutKey,
+ if (mDataStore.setKeyboardLayout(identifier.toString(), datastoreKey,
keyboardLayoutDescriptor)) {
if (DEBUG) {
Slog.d(TAG, "setKeyboardLayoutForInputDevice() " + identifier
- + " key: " + layoutKey
+ + " key: " + datastoreKey
+ " keyboardLayoutDescriptor: " + keyboardLayoutDescriptor);
}
mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
@@ -635,6 +654,12 @@ class KeyboardLayoutManager implements InputManager.InputDeviceListener {
if (layout != null) {
return new KeyboardLayoutSelectionResult(layout, LAYOUT_SELECTION_CRITERIA_USER);
}
+
+ layout = mDataStore.getKeyboardLayout(keyboardIdentifier.toString(),
+ GLOBAL_OVERRIDE_KEY);
+ if (layout != null) {
+ return new KeyboardLayoutSelectionResult(layout, LAYOUT_SELECTION_CRITERIA_DEVICE);
+ }
}
synchronized (mKeyboardLayoutCache) {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
index b9352edf9230..ddace179348c 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java
@@ -42,6 +42,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import java.util.Collection;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -372,10 +373,12 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
/* package */ void onEndpointSessionOpenRequest(
int sessionId, HubEndpointInfo initiator, String serviceDescriptor) {
- boolean success =
+ Optional<Byte> error =
onEndpointSessionOpenRequestInternal(sessionId, initiator, serviceDescriptor);
- if (!success) {
- cleanupSessionResources(sessionId);
+ if (error.isPresent()) {
+ halCloseEndpointSessionNoThrow(sessionId, error.get());
+ onCloseEndpointSession(sessionId, error.get());
+ // Resource cleanup is done in onCloseEndpointSession
}
}
@@ -422,7 +425,7 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
}
}
- private boolean onEndpointSessionOpenRequestInternal(
+ private Optional<Byte> onEndpointSessionOpenRequestInternal(
int sessionId, HubEndpointInfo initiator, String serviceDescriptor) {
if (!hasEndpointPermissions(initiator)) {
Log.e(
@@ -431,22 +434,21 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
+ initiator
+ " doesn't have permission for "
+ mEndpointInfo);
- halCloseEndpointSessionNoThrow(sessionId, Reason.PERMISSION_DENIED);
- return false;
+ return Optional.of(Reason.PERMISSION_DENIED);
}
synchronized (mOpenSessionLock) {
if (hasSessionId(sessionId)) {
Log.e(TAG, "Existing session in onEndpointSessionOpenRequest: id=" + sessionId);
- halCloseEndpointSessionNoThrow(sessionId, Reason.UNSPECIFIED);
- return false;
+ return Optional.of(Reason.UNSPECIFIED);
}
mSessionInfoMap.put(sessionId, new SessionInfo(initiator, true));
}
- return invokeCallback(
+ boolean success = invokeCallback(
(consumer) ->
consumer.onSessionOpenRequest(sessionId, initiator, serviceDescriptor));
+ return success ? Optional.empty() : Optional.of(Reason.UNSPECIFIED);
}
private byte onMessageReceivedInternal(int sessionId, HubMessage message) {
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java b/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java
index 2e0bb4f88485..18f2f48b80a3 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.telephony.TelephonyCallback;
@@ -38,6 +39,7 @@ import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemConfig;
+import java.util.List;
import java.util.function.Consumer;
/**
@@ -60,21 +62,35 @@ public class MediaProjectionStopController {
private final TelephonyManager mTelephonyManager;
private final AppOpsManager mAppOpsManager;
private final PackageManager mPackageManager;
- private final RoleManager mRoleManager;
+ private final RoleHolderProvider mRoleHolderProvider;
private final ContentResolver mContentResolver;
private boolean mIsInCall;
private long mLastCallStartTimeMillis;
+
+ @VisibleForTesting
+ interface RoleHolderProvider {
+ List<String> getRoleHoldersAsUser(String roleName, UserHandle user);
+ }
+
public MediaProjectionStopController(Context context, Consumer<Integer> stopReasonConsumer) {
+ this(context, stopReasonConsumer,
+ (roleName, user) -> context.getSystemService(RoleManager.class)
+ .getRoleHoldersAsUser(roleName, user));
+ }
+
+ @VisibleForTesting
+ MediaProjectionStopController(Context context, Consumer<Integer> stopReasonConsumer,
+ RoleHolderProvider roleHolderProvider) {
mStopReasonConsumer = stopReasonConsumer;
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mTelecomManager = context.getSystemService(TelecomManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
mPackageManager = context.getPackageManager();
- mRoleManager = context.getSystemService(RoleManager.class);
mContentResolver = context.getContentResolver();
+ mRoleHolderProvider = roleHolderProvider;
}
/**
@@ -146,8 +162,9 @@ public class MediaProjectionStopController {
Slog.v(TAG, "Continuing MediaProjection for package with OP_PROJECT_MEDIA AppOp ");
return true;
}
- if (mRoleManager.getRoleHoldersAsUser(AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
- projectionGrant.userHandle).contains(projectionGrant.packageName)) {
+ if (mRoleHolderProvider.getRoleHoldersAsUser(
+ AssociationRequest.DEVICE_PROFILE_APP_STREAMING, projectionGrant.userHandle)
+ .contains(projectionGrant.packageName)) {
Slog.v(TAG, "Continuing MediaProjection for package holding app streaming role.");
return true;
}
@@ -177,10 +194,6 @@ public class MediaProjectionStopController {
*/
public boolean isStartForbidden(
MediaProjectionManagerService.MediaProjection projectionGrant) {
- if (!android.companion.virtualdevice.flags.Flags.mediaProjectionKeyguardRestrictions()) {
- return false;
- }
-
if (!mKeyguardManager.isKeyguardLocked()) {
return false;
}
@@ -194,9 +207,6 @@ public class MediaProjectionStopController {
@VisibleForTesting
void onKeyguardLockedStateChanged(boolean isKeyguardLocked) {
if (!isKeyguardLocked) return;
- if (!android.companion.virtualdevice.flags.Flags.mediaProjectionKeyguardRestrictions()) {
- return;
- }
mStopReasonConsumer.accept(STOP_REASON_KEYGUARD);
}
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java
index f6c94a7d9a5a..d23a8638803b 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -73,6 +73,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
import com.android.server.utils.Slogf;
@@ -122,6 +123,13 @@ public class MediaQualityService extends SystemService {
private SharedPreferences mPictureProfileSharedPreference;
private SharedPreferences mSoundProfileSharedPreference;
+ // A global lock for picture profile objects.
+ private final Object mPictureProfileLock = new Object();
+ // A global lock for sound profile objects.
+ private final Object mSoundProfileLock = new Object();
+ // A global lock for ambient backlight objects.
+ private final Object mAmbientBacklightLock = new Object();
+
public MediaQualityService(Context context) {
super(context);
mContext = context;
@@ -254,6 +262,7 @@ public class MediaQualityService extends SystemService {
// TODO: Add additional APIs. b/373951081
private final class BinderService extends IMediaQualityManager.Stub {
+ @GuardedBy("mPictureProfileLock")
@Override
public PictureProfile createPictureProfile(PictureProfile pp, UserHandle user) {
if ((pp.getPackageName() != null && !pp.getPackageName().isEmpty()
@@ -263,24 +272,27 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ synchronized (mPictureProfileLock) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- ContentValues values = getContentValues(null,
- pp.getProfileType(),
- pp.getName(),
- pp.getPackageName() == null || pp.getPackageName().isEmpty()
- ? getPackageOfCallingUid() : pp.getPackageName(),
- pp.getInputId(),
- pp.getParameters());
+ ContentValues values = getContentValues(null,
+ pp.getProfileType(),
+ pp.getName(),
+ pp.getPackageName() == null || pp.getPackageName().isEmpty()
+ ? getPackageOfCallingUid() : pp.getPackageName(),
+ pp.getInputId(),
+ pp.getParameters());
- // id is auto-generated by SQLite upon successful insertion of row
- Long id = db.insert(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
- null, values);
- populateTempIdMap(mPictureProfileTempIdMap, id);
- String value = mPictureProfileTempIdMap.getValue(id);
- pp.setProfileId(value);
- notifyOnPictureProfileAdded(value, pp, Binder.getCallingUid(), Binder.getCallingPid());
- return pp;
+ // id is auto-generated by SQLite upon successful insertion of row
+ Long id = db.insert(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ null, values);
+ populateTempIdMap(mPictureProfileTempIdMap, id);
+ String value = mPictureProfileTempIdMap.getValue(id);
+ pp.setProfileId(value);
+ notifyOnPictureProfileAdded(value, pp, Binder.getCallingUid(),
+ Binder.getCallingPid());
+ return pp;
+ }
}
private void notifyHalOnPictureProfileChange(Long dbId, PersistableBundle params) {
@@ -307,6 +319,7 @@ public class MediaQualityService extends SystemService {
return toReturn;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void updatePictureProfile(String id, PictureProfile pp, UserHandle user) {
Long dbId = mPictureProfileTempIdMap.getKey(id);
@@ -315,12 +328,13 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
- ContentValues values = getContentValues(dbId,
- pp.getProfileType(),
- pp.getName(),
- pp.getPackageName(),
- pp.getInputId(),
- pp.getParameters());
+ synchronized (mPictureProfileLock) {
+ ContentValues values = getContentValues(dbId,
+ pp.getProfileType(),
+ pp.getName(),
+ pp.getPackageName(),
+ pp.getInputId(),
+ pp.getParameters());
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
db.replace(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
@@ -328,6 +342,7 @@ public class MediaQualityService extends SystemService {
notifyOnPictureProfileUpdated(mPictureProfileTempIdMap.getValue(dbId),
getPictureProfile(dbId), Binder.getCallingUid(), Binder.getCallingPid());
notifyHalOnPictureProfileChange(dbId, pp.getParameters());
+ }
}
private boolean hasPermissionToUpdatePictureProfile(Long dbId, PictureProfile toUpdate) {
@@ -338,30 +353,33 @@ public class MediaQualityService extends SystemService {
&& fromDb.getName().equals(getPackageOfCallingUid());
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void removePictureProfile(String id, UserHandle user) {
- Long dbId = mPictureProfileTempIdMap.getKey(id);
+ synchronized (mPictureProfileLock) {
+ Long dbId = mPictureProfileTempIdMap.getKey(id);
- PictureProfile toDelete = getPictureProfile(dbId);
- if (!hasPermissionToRemovePictureProfile(toDelete)) {
- notifyOnPictureProfileError(id, PictureProfile.ERROR_NO_PERMISSION,
- Binder.getCallingUid(), Binder.getCallingPid());
- }
+ PictureProfile toDelete = getPictureProfile(dbId);
+ if (!hasPermissionToRemovePictureProfile(toDelete)) {
+ notifyOnPictureProfileError(id, PictureProfile.ERROR_NO_PERMISSION,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
- if (dbId != null) {
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- String selection = BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArgs = {Long.toString(dbId)};
- int result = db.delete(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME, selection,
- selectionArgs);
- if (result == 0) {
- notifyOnPictureProfileError(id, PictureProfile.ERROR_INVALID_ARGUMENT,
+ if (dbId != null) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArgs = {Long.toString(dbId)};
+ int result = db.delete(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ selection, selectionArgs);
+ if (result == 0) {
+ notifyOnPictureProfileError(id, PictureProfile.ERROR_INVALID_ARGUMENT,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+ notifyOnPictureProfileRemoved(mPictureProfileTempIdMap.getValue(dbId), toDelete,
Binder.getCallingUid(), Binder.getCallingPid());
+ mPictureProfileTempIdMap.remove(dbId);
+ notifyHalOnPictureProfileChange(dbId, null);
}
- notifyOnPictureProfileRemoved(mPictureProfileTempIdMap.getValue(dbId), toDelete,
- Binder.getCallingUid(), Binder.getCallingPid());
- mPictureProfileTempIdMap.remove(dbId);
- notifyHalOnPictureProfileChange(dbId, null);
}
}
@@ -372,6 +390,7 @@ public class MediaQualityService extends SystemService {
return false;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public PictureProfile getPictureProfile(int type, String name, Bundle options,
UserHandle user) {
@@ -382,23 +401,27 @@ public class MediaQualityService extends SystemService {
+ BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {Integer.toString(type), name, getPackageOfCallingUid()};
- try (
- Cursor cursor = getCursorAfterQuerying(
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
- getMediaProfileColumns(includeParams), selection, selectionArguments)
- ) {
- int count = cursor.getCount();
- if (count == 0) {
- return null;
- }
- if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for type=%d and name=%s"
- + " in %s. Should only ever be 0 or 1.", count, type, name,
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
- return null;
+ synchronized (mPictureProfileLock) {
+ try (
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ getMediaProfileColumns(includeParams), selection,
+ selectionArguments)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d "
+ + "entries found for type=%d and name=%s in %s. Should"
+ + " only ever be 0 or 1.", count, type, name,
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
+ return null;
+ }
+ cursor.moveToFirst();
+ return convertCursorToPictureProfileWithTempId(cursor);
}
- cursor.moveToFirst();
- return convertCursorToPictureProfileWithTempId(cursor);
}
}
@@ -416,9 +439,9 @@ public class MediaQualityService extends SystemService {
return null;
}
if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for id=%d"
- + " in %s. Should only ever be 0 or 1.", count, dbId,
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d entries "
+ + "found for id=%d in %s. Should only ever be 0 or 1.",
+ count, dbId, mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
return null;
}
cursor.moveToFirst();
@@ -426,6 +449,7 @@ public class MediaQualityService extends SystemService {
}
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<PictureProfile> getPictureProfilesByPackage(
String packageName, Bundle options, UserHandle user) {
@@ -434,14 +458,17 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
- String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
- String[] selectionArguments = {packageName};
- return getPictureProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
- selection, selectionArguments);
+ synchronized (mPictureProfileLock) {
+ boolean includeParams =
+ options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
+ String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
+ String[] selectionArguments = {packageName};
+ return getPictureProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
+ selection, selectionArguments);
+ }
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<PictureProfile> getAvailablePictureProfiles(Bundle options, UserHandle user) {
String packageName = getPackageOfCallingUid();
@@ -451,6 +478,7 @@ public class MediaQualityService extends SystemService {
return new ArrayList<>();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public boolean setDefaultPictureProfile(String profileId, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -810,6 +838,7 @@ public class MediaQualityService extends SystemService {
return (PictureParameter[]) pictureParams.toArray();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<String> getPictureProfilePackageNames(UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -817,42 +846,51 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
String [] column = {BaseParameters.PARAMETER_PACKAGE};
- List<PictureProfile> pictureProfiles = getPictureProfilesBasedOnConditions(column,
- null, null);
- return pictureProfiles.stream()
- .map(PictureProfile::getPackageName)
- .distinct()
- .collect(Collectors.toList());
+ synchronized (mPictureProfileLock) {
+ List<PictureProfile> pictureProfiles = getPictureProfilesBasedOnConditions(column,
+ null, null);
+ return pictureProfiles.stream()
+ .map(PictureProfile::getPackageName)
+ .distinct()
+ .collect(Collectors.toList());
+ }
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<PictureProfileHandle> getPictureProfileHandle(String[] ids, UserHandle user) {
List<PictureProfileHandle> toReturn = new ArrayList<>();
- for (String id : ids) {
- Long key = mPictureProfileTempIdMap.getKey(id);
- if (key != null) {
- toReturn.add(new PictureProfileHandle(key));
- } else {
- toReturn.add(null);
+ synchronized (mPictureProfileLock) {
+ for (String id : ids) {
+ Long key = mPictureProfileTempIdMap.getKey(id);
+ if (key != null) {
+ toReturn.add(new PictureProfileHandle(key));
+ } else {
+ toReturn.add(null);
+ }
}
}
return toReturn;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<SoundProfileHandle> getSoundProfileHandle(String[] ids, UserHandle user) {
List<SoundProfileHandle> toReturn = new ArrayList<>();
- for (String id : ids) {
- Long key = mSoundProfileTempIdMap.getKey(id);
- if (key != null) {
- toReturn.add(new SoundProfileHandle(key));
- } else {
- toReturn.add(null);
+ synchronized (mSoundProfileLock) {
+ for (String id : ids) {
+ Long key = mSoundProfileTempIdMap.getKey(id);
+ if (key != null) {
+ toReturn.add(new SoundProfileHandle(key));
+ } else {
+ toReturn.add(null);
+ }
}
}
return toReturn;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public SoundProfile createSoundProfile(SoundProfile sp, UserHandle user) {
if ((sp.getPackageName() != null && !sp.getPackageName().isEmpty()
@@ -861,24 +899,28 @@ public class MediaQualityService extends SystemService {
notifyOnSoundProfileError(null, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- ContentValues values = getContentValues(null,
- sp.getProfileType(),
- sp.getName(),
- sp.getPackageName() == null || sp.getPackageName().isEmpty()
- ? getPackageOfCallingUid() : sp.getPackageName(),
- sp.getInputId(),
- sp.getParameters());
+ synchronized (mSoundProfileLock) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- // id is auto-generated by SQLite upon successful insertion of row
- Long id = db.insert(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
- null, values);
- populateTempIdMap(mSoundProfileTempIdMap, id);
- String value = mSoundProfileTempIdMap.getValue(id);
- sp.setProfileId(value);
- notifyOnSoundProfileAdded(value, sp, Binder.getCallingUid(), Binder.getCallingPid());
- return sp;
+ ContentValues values = getContentValues(null,
+ sp.getProfileType(),
+ sp.getName(),
+ sp.getPackageName() == null || sp.getPackageName().isEmpty()
+ ? getPackageOfCallingUid() : sp.getPackageName(),
+ sp.getInputId(),
+ sp.getParameters());
+
+ // id is auto-generated by SQLite upon successful insertion of row
+ Long id = db.insert(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ null, values);
+ populateTempIdMap(mSoundProfileTempIdMap, id);
+ String value = mSoundProfileTempIdMap.getValue(id);
+ sp.setProfileId(value);
+ notifyOnSoundProfileAdded(value, sp, Binder.getCallingUid(),
+ Binder.getCallingPid());
+ return sp;
+ }
}
private void notifyHalOnSoundProfileChange(Long dbId, PersistableBundle params) {
@@ -903,6 +945,7 @@ public class MediaQualityService extends SystemService {
return toReturn;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void updateSoundProfile(String id, SoundProfile sp, UserHandle user) {
Long dbId = mSoundProfileTempIdMap.getKey(id);
@@ -911,18 +954,20 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
- ContentValues values = getContentValues(dbId,
- sp.getProfileType(),
- sp.getName(),
- sp.getPackageName(),
- sp.getInputId(),
- sp.getParameters());
+ synchronized (mSoundProfileLock) {
+ ContentValues values = getContentValues(dbId,
+ sp.getProfileType(),
+ sp.getName(),
+ sp.getPackageName(),
+ sp.getInputId(),
+ sp.getParameters());
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
db.replace(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, null, values);
notifyOnSoundProfileUpdated(mSoundProfileTempIdMap.getValue(dbId),
getSoundProfile(dbId), Binder.getCallingUid(), Binder.getCallingPid());
notifyHalOnSoundProfileChange(dbId, sp.getParameters());
+ }
}
private boolean hasPermissionToUpdateSoundProfile(Long dbId, SoundProfile sp) {
@@ -933,29 +978,32 @@ public class MediaQualityService extends SystemService {
&& fromDb.getName().equals(getPackageOfCallingUid());
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void removeSoundProfile(String id, UserHandle user) {
- Long dbId = mSoundProfileTempIdMap.getKey(id);
- SoundProfile toDelete = getSoundProfile(dbId);
- if (!hasPermissionToRemoveSoundProfile(toDelete)) {
- notifyOnSoundProfileError(id, SoundProfile.ERROR_NO_PERMISSION,
- Binder.getCallingUid(), Binder.getCallingPid());
- }
-
- if (dbId != null) {
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- String selection = BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArgs = {Long.toString(dbId)};
- int result = db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, selection,
- selectionArgs);
- if (result == 0) {
- notifyOnSoundProfileError(id, SoundProfile.ERROR_INVALID_ARGUMENT,
+ synchronized (mSoundProfileLock) {
+ Long dbId = mSoundProfileTempIdMap.getKey(id);
+ SoundProfile toDelete = getSoundProfile(dbId);
+ if (!hasPermissionToRemoveSoundProfile(toDelete)) {
+ notifyOnSoundProfileError(id, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
- notifyOnSoundProfileRemoved(mSoundProfileTempIdMap.getValue(dbId), toDelete,
- Binder.getCallingUid(), Binder.getCallingPid());
- mSoundProfileTempIdMap.remove(dbId);
- notifyHalOnSoundProfileChange(dbId, null);
+ if (dbId != null) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArgs = {Long.toString(dbId)};
+ int result = db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ selection,
+ selectionArgs);
+ if (result == 0) {
+ notifyOnSoundProfileError(id, SoundProfile.ERROR_INVALID_ARGUMENT,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+ notifyOnSoundProfileRemoved(mSoundProfileTempIdMap.getValue(dbId), toDelete,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ mSoundProfileTempIdMap.remove(dbId);
+ notifyHalOnSoundProfileChange(dbId, null);
+ }
}
}
@@ -966,6 +1014,7 @@ public class MediaQualityService extends SystemService {
return false;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public SoundProfile getSoundProfile(int type, String name, Bundle options,
UserHandle user) {
@@ -976,23 +1025,27 @@ public class MediaQualityService extends SystemService {
+ BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {String.valueOf(type), name, getPackageOfCallingUid()};
- try (
- Cursor cursor = getCursorAfterQuerying(
- mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
- getMediaProfileColumns(includeParams), selection, selectionArguments)
- ) {
- int count = cursor.getCount();
- if (count == 0) {
- return null;
- }
- if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for name=%s"
- + " in %s. Should only ever be 0 or 1.", count, name,
- mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
- return null;
+ synchronized (mSoundProfileLock) {
+ try (
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ getMediaProfileColumns(includeParams), selection,
+ selectionArguments)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d "
+ + "entries found for name=%s in %s. Should only ever "
+ + "be 0 or 1.", String.valueOf(count), name,
+ mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
+ return null;
+ }
+ cursor.moveToFirst();
+ return convertCursorToSoundProfileWithTempId(cursor);
}
- cursor.moveToFirst();
- return convertCursorToSoundProfileWithTempId(cursor);
}
}
@@ -1010,9 +1063,9 @@ public class MediaQualityService extends SystemService {
return null;
}
if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for id=%s "
- + "in %s. Should only ever be 0 or 1.", count, dbId,
- mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d entries "
+ + "found for id=%s in %s. Should only ever be 0 or 1.", count,
+ dbId, mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
return null;
}
cursor.moveToFirst();
@@ -1020,6 +1073,7 @@ public class MediaQualityService extends SystemService {
}
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<SoundProfile> getSoundProfilesByPackage(
String packageName, Bundle options, UserHandle user) {
@@ -1028,14 +1082,17 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
- String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
- String[] selectionArguments = {packageName};
- return getSoundProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
- selection, selectionArguments);
+ synchronized (mSoundProfileLock) {
+ boolean includeParams =
+ options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
+ String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
+ String[] selectionArguments = {packageName};
+ return getSoundProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
+ selection, selectionArguments);
+ }
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<SoundProfile> getAvailableSoundProfiles(Bundle options, UserHandle user) {
String packageName = getPackageOfCallingUid();
@@ -1045,6 +1102,7 @@ public class MediaQualityService extends SystemService {
return new ArrayList<>();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public boolean setDefaultSoundProfile(String profileId, UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1161,6 +1219,7 @@ public class MediaQualityService extends SystemService {
return (SoundParameter[]) soundParams.toArray();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<String> getSoundProfilePackageNames(UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1168,12 +1227,15 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
String [] column = {BaseParameters.PARAMETER_NAME};
- List<SoundProfile> soundProfiles = getSoundProfilesBasedOnConditions(column,
- null, null);
- return soundProfiles.stream()
- .map(SoundProfile::getPackageName)
- .distinct()
- .collect(Collectors.toList());
+
+ synchronized (mSoundProfileLock) {
+ List<SoundProfile> soundProfiles = getSoundProfilesBasedOnConditions(column,
+ null, null);
+ return soundProfiles.stream()
+ .map(SoundProfile::getPackageName)
+ .distinct()
+ .collect(Collectors.toList());
+ }
}
private String getPackageOfCallingUid() {
@@ -1539,6 +1601,7 @@ public class MediaQualityService extends SystemService {
userState.mSoundProfileCallbacks.finishBroadcast();
}
+ //TODO: need lock here?
@Override
public void registerPictureProfileCallback(final IPictureProfileCallback callback) {
int callingPid = Binder.getCallingPid();
@@ -1549,6 +1612,7 @@ public class MediaQualityService extends SystemService {
Pair.create(callingPid, callingUid));
}
+ //TODO: need lock here?
@Override
public void registerSoundProfileCallback(final ISoundProfileCallback callback) {
int callingPid = Binder.getCallingPid();
@@ -1586,6 +1650,7 @@ public class MediaQualityService extends SystemService {
}
}
+ @GuardedBy("mAmbientBacklightLock")
@Override
public void setAmbientBacklightSettings(
AmbientBacklightSettings settings, UserHandle user) {
@@ -1624,6 +1689,7 @@ public class MediaQualityService extends SystemService {
}
}
+ @GuardedBy("mAmbientBacklightLock")
@Override
public void setAmbientBacklightEnabled(boolean enabled, UserHandle user) {
if (DEBUG) {
@@ -1643,12 +1709,14 @@ public class MediaQualityService extends SystemService {
}
}
+ //TODO: do I need a lock here?
@Override
public List<ParameterCapability> getParameterCapabilities(
List<String> names, UserHandle user) {
return new ArrayList<>();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<String> getPictureProfileAllowList(UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -1663,6 +1731,7 @@ public class MediaQualityService extends SystemService {
return new ArrayList<>();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void setPictureProfileAllowList(List<String> packages, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -1674,6 +1743,7 @@ public class MediaQualityService extends SystemService {
editor.commit();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<String> getSoundProfileAllowList(UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1688,6 +1758,7 @@ public class MediaQualityService extends SystemService {
return new ArrayList<>();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void setSoundProfileAllowList(List<String> packages, UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1704,70 +1775,81 @@ public class MediaQualityService extends SystemService {
return false;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void setAutoPictureQualityEnabled(boolean enabled, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
notifyOnPictureProfileError(null, PictureProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
-
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoPqSupported()) {
- mMediaQuality.setAutoPqEnabled(enabled);
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoPqSupported()) {
+ mMediaQuality.setAutoPqEnabled(enabled);
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set auto picture quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to set auto picture quality", e);
}
}
+ @GuardedBy("mPictureProfileLock")
@Override
public boolean isAutoPictureQualityEnabled(UserHandle user) {
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoPqSupported()) {
- return mMediaQuality.getAutoPqEnabled();
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoPqSupported()) {
+ return mMediaQuality.getAutoPqEnabled();
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get auto picture quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get auto picture quality", e);
+ return false;
}
- return false;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void setSuperResolutionEnabled(boolean enabled, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
notifyOnPictureProfileError(null, PictureProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
-
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoSrSupported()) {
- mMediaQuality.setAutoSrEnabled(enabled);
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoSrSupported()) {
+ mMediaQuality.setAutoSrEnabled(enabled);
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set super resolution", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to set super resolution", e);
}
}
+ @GuardedBy("mPictureProfileLock")
@Override
public boolean isSuperResolutionEnabled(UserHandle user) {
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoSrSupported()) {
- return mMediaQuality.getAutoSrEnabled();
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoSrSupported()) {
+ return mMediaQuality.getAutoSrEnabled();
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get super resolution", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get super resolution", e);
+ return false;
}
- return false;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void setAutoSoundQualityEnabled(boolean enabled, UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1775,31 +1857,37 @@ public class MediaQualityService extends SystemService {
Binder.getCallingUid(), Binder.getCallingPid());
}
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoAqSupported()) {
- mMediaQuality.setAutoAqEnabled(enabled);
+ synchronized (mSoundProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoAqSupported()) {
+ mMediaQuality.setAutoAqEnabled(enabled);
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set auto sound quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to set auto sound quality", e);
}
}
+ @GuardedBy("mSoundProfileLock")
@Override
public boolean isAutoSoundQualityEnabled(UserHandle user) {
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoAqSupported()) {
- return mMediaQuality.getAutoAqEnabled();
+ synchronized (mSoundProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoAqSupported()) {
+ return mMediaQuality.getAutoAqEnabled();
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get auto sound quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get auto sound quality", e);
+ return false;
}
- return false;
}
+ @GuardedBy("mAmbientBacklightLock")
@Override
public boolean isAmbientBacklightEnabled(UserHandle user) {
return false;
@@ -1853,6 +1941,7 @@ public class MediaQualityService extends SystemService {
}
}
+ //TODO: used by both picture and sound. can i add both locks?
private UserState getOrCreateUserStateLocked(int userId) {
UserState userState = getUserStateLocked(userId);
if (userState == null) {
@@ -1862,6 +1951,7 @@ public class MediaQualityService extends SystemService {
return userState;
}
+ //TODO: used by both picture and sound. can i add both locks?
private UserState getUserStateLocked(int userId) {
return mUserStates.get(userId);
}
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 5a425057ea89..89902f7f8321 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -101,15 +101,4 @@ public interface NotificationDelegate {
void onNotificationFeedbackReceived(String key, Bundle feedback);
void prepareForPossibleShutdown();
-
- /**
- * Called when the notification should be unbundled.
- * @param key the notification key
- */
- void unbundleNotification(String key);
- /**
- * Called when the notification should be rebundled.
- * @param key the notification key
- */
- void rebundleNotification(String key);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0d3c18ac339f..a16b122771ef 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -26,6 +26,8 @@ import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_RECEIVE_SENSITIVE_NOTIFICATIONS;
import static android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR;
import static android.app.Flags.lifetimeExtensionRefactor;
+import static android.app.Flags.nmSummarization;
+import static android.app.Flags.nmSummarizationUi;
import static android.app.Flags.notificationClassificationUi;
import static android.app.Flags.redactSensitiveContentNotificationsOnLockscreen;
import static android.app.Flags.sortSectionByTime;
@@ -106,6 +108,7 @@ import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROU
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
+import static android.service.notification.Adjustment.KEY_SUMMARIZATION;
import static android.service.notification.Adjustment.KEY_TYPE;
import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION;
import static android.service.notification.Adjustment.TYPE_PROMOTION;
@@ -290,6 +293,7 @@ import android.permission.PermissionManager;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.notification.Adjustment;
+import android.service.notification.Adjustment.Types;
import android.service.notification.Condition;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.DeviceEffectsApplier;
@@ -417,6 +421,7 @@ import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
/** {@hide} */
@@ -1865,74 +1870,183 @@ public class NotificationManagerService extends SystemService {
mAssistants.notifyAssistantFeedbackReceived(r, feedback);
}
}
+ };
- @Override
- public void unbundleNotification(String key) {
- if (!(notificationClassification() && notificationRegroupOnClassification())) {
- return;
- }
- synchronized (mNotificationLock) {
- NotificationRecord r = mNotificationsByKey.get(key);
- if (r == null) {
- return;
- }
+ private void unclassifyNotificationsForUser(final int userId) {
+ if (DBG) {
+ Slog.v(TAG, "unclassifyForUser: " + userId);
+ }
+ unclassifyNotificationsFiltered((r) -> r.getUserId() == userId);
+ }
- if (DBG) {
- Slog.v(TAG, "unbundleNotification: " + r);
- }
+ private void unclassifyNotificationsForUid(final int userId, @NonNull final String pkg) {
+ if (DBG) {
+ Slog.v(TAG, "unclassifyForUid userId: " + userId + " pkg: " + pkg);
+ }
+ unclassifyNotificationsFiltered((r) ->
+ r.getUserId() == userId
+ && Objects.equals(r.getSbn().getPackageName(), pkg));
+ }
+
+ private void unclassifyNotificationsForUserAndType(final int userId,
+ final @Types int bundleType) {
+ if (DBG) {
+ Slog.v(TAG,
+ "unclassifyForUserAndType userId: " + userId + " bundleType: " + bundleType);
+ }
+ final String bundleChannelId = NotificationChannel.getChannelIdForBundleType(bundleType);
+ unclassifyNotificationsFiltered((r) ->
+ r.getUserId() == userId
+ && r.getChannel() != null
+ && Objects.equals(bundleChannelId, r.getChannel().getId()));
+ }
- boolean hasOriginalSummary = false;
- if (r.getSbn().isAppGroup() && r.getNotification().isGroupChild()) {
- final String oldGroupKey = GroupHelper.getFullAggregateGroupKey(
- r.getSbn().getPackageName(), r.getOriginalGroupKey(), r.getUserId());
- NotificationRecord groupSummary = mSummaryByGroupKey.get(oldGroupKey);
- // We only care about app-provided valid groups
- hasOriginalSummary = (groupSummary != null
- && !GroupHelper.isAggregatedGroup(groupSummary));
+ private void unclassifyNotificationsFiltered(Predicate<NotificationRecord> filter) {
+ if (!(notificationClassificationUi() && notificationRegroupOnClassification())) {
+ return;
+ }
+ synchronized (mNotificationLock) {
+ for (int i = 0; i < mEnqueuedNotifications.size(); i++) {
+ final NotificationRecord r = mEnqueuedNotifications.get(i);
+ if (filter.test(r)) {
+ unclassifyNotificationLocked(r);
}
+ }
- // Only NotificationRecord's mChannel is updated when bundled, the Notification
- // mChannelId will always be the original channel.
- String origChannelId = r.getNotification().getChannelId();
- NotificationChannel originalChannel = mPreferencesHelper.getNotificationChannel(
- r.getSbn().getPackageName(), r.getUid(), origChannelId, false);
- if (originalChannel != null && !origChannelId.equals(r.getChannel().getId())) {
- r.updateNotificationChannel(originalChannel);
- mGroupHelper.onNotificationUnbundled(r, hasOriginalSummary);
+ for (int i = 0; i < mNotificationList.size(); i++) {
+ final NotificationRecord r = mNotificationList.get(i);
+ if (filter.test(r)) {
+ unclassifyNotificationLocked(r);
}
}
}
+ }
+
+ @GuardedBy("mNotificationLock")
+ private void unclassifyNotificationLocked(@NonNull final NotificationRecord r) {
+ if (DBG) {
+ Slog.v(TAG, "unclassifyNotification: " + r);
+ }
- @Override
- public void rebundleNotification(String key) {
- if (!(notificationClassification() && notificationRegroupOnClassification())) {
+ boolean hasOriginalSummary = false;
+ if (r.getSbn().isAppGroup() && r.getNotification().isGroupChild()) {
+ final String oldGroupKey = GroupHelper.getFullAggregateGroupKey(
+ r.getSbn().getPackageName(), r.getOriginalGroupKey(), r.getUserId());
+ NotificationRecord groupSummary = mSummaryByGroupKey.get(oldGroupKey);
+ // We only care about app-provided valid groups
+ hasOriginalSummary = (groupSummary != null
+ && !GroupHelper.isAggregatedGroup(groupSummary));
+ }
+
+ // Only NotificationRecord's mChannel is updated when bundled, the Notification
+ // mChannelId will always be the original channel.
+ String origChannelId = r.getNotification().getChannelId();
+ NotificationChannel originalChannel = mPreferencesHelper.getNotificationChannel(
+ r.getSbn().getPackageName(), r.getUid(), origChannelId, false);
+ String currChannelId = r.getChannel().getId();
+ boolean isBundled = NotificationChannel.SYSTEM_RESERVED_IDS.contains(currChannelId);
+ if (originalChannel != null && !origChannelId.equals(currChannelId) && isBundled) {
+ r.updateNotificationChannel(originalChannel);
+ mGroupHelper.onNotificationUnbundled(r, hasOriginalSummary);
+ }
+ }
+
+ @VisibleForTesting
+ void unclassifyNotification(final String key) {
+ if (!(notificationClassificationUi() && notificationRegroupOnClassification())) {
+ return;
+ }
+ synchronized (mNotificationLock) {
+ NotificationRecord r = mNotificationsByKey.get(key);
+ if (r == null) {
return;
}
- synchronized (mNotificationLock) {
- NotificationRecord r = mNotificationsByKey.get(key);
- if (r == null) {
- return;
- }
+ unclassifyNotificationLocked(r);
+ }
+ }
- if (DBG) {
- Slog.v(TAG, "rebundleNotification: " + r);
+ @VisibleForTesting
+ void reclassifyNotification(String key) {
+ if (!(notificationClassificationUi() && notificationRegroupOnClassification())) {
+ return;
+ }
+ synchronized (mNotificationLock) {
+ NotificationRecord r = mNotificationsByKey.get(key);
+ if (r == null) {
+ return;
+ }
+ reclassifyNotificationLocked(r, true);
+ }
+ }
+
+ private void reclassifyNotificationsFiltered(Predicate<NotificationRecord> filter) {
+ if (!(notificationClassificationUi() && notificationRegroupOnClassification())) {
+ return;
+ }
+ synchronized (mNotificationLock) {
+ for (int i = 0; i < mEnqueuedNotifications.size(); i++) {
+ final NotificationRecord r = mEnqueuedNotifications.get(i);
+ if (filter.test(r)) {
+ reclassifyNotificationLocked(r, false);
}
+ }
- if (r.getBundleType() != Adjustment.TYPE_OTHER) {
- final Bundle classifBundle = new Bundle();
- classifBundle.putInt(KEY_TYPE, r.getBundleType());
- Adjustment adj = new Adjustment(r.getSbn().getPackageName(), r.getKey(),
- classifBundle, "rebundle", r.getUserId());
- applyAdjustmentLocked(r, adj, /* isPosted= */ true);
- mRankingHandler.requestSort();
- } else {
- if (DBG) {
- Slog.w(TAG, "Can't rebundle. No valid bundle type for: " + r);
- }
+ for (int i = 0; i < mNotificationList.size(); i++) {
+ final NotificationRecord r = mNotificationList.get(i);
+ if (filter.test(r)) {
+ reclassifyNotificationLocked(r, true);
}
}
}
- };
+ }
+
+ private void reclassifyNotificationsForUserAndType(final int userId,
+ final @Types int bundleType) {
+ if (DBG) {
+ Slog.v(TAG, "reclassifyNotificationsForUserAndType userId: " + userId + " bundleType: "
+ + bundleType);
+ }
+ reclassifyNotificationsFiltered(
+ (r) -> r.getUserId() == userId && r.getBundleType() == bundleType);
+ }
+
+ private void reclassifyNotificationsForUid(final int userId, final String pkg) {
+ if (DBG) {
+ Slog.v(TAG, "reclassifyNotificationsForUid userId: " + userId + " pkg: " + pkg);
+ }
+ reclassifyNotificationsFiltered((r) ->
+ r.getUserId() == userId && Objects.equals(r.getSbn().getPackageName(), pkg));
+ }
+
+ private void reclassifyNotificationsForUser(final int userId) {
+ if (DBG) {
+ Slog.v(TAG, "reclassifyAllNotificationsForUser: " + userId);
+ }
+ reclassifyNotificationsFiltered((r) -> r.getUserId() == userId);
+ }
+
+ @GuardedBy("mNotificationLock")
+ private void reclassifyNotificationLocked(@NonNull final NotificationRecord r,
+ final boolean isPosted) {
+ if (DBG) {
+ Slog.v(TAG, "reclassifyNotification: " + r);
+ }
+
+ boolean isBundled = NotificationChannel.SYSTEM_RESERVED_IDS.contains(
+ r.getChannel().getId());
+ if (r.getBundleType() != Adjustment.TYPE_OTHER && !isBundled) {
+ final Bundle classifBundle = new Bundle();
+ classifBundle.putInt(KEY_TYPE, r.getBundleType());
+ Adjustment adj = new Adjustment(r.getSbn().getPackageName(), r.getKey(),
+ classifBundle, "reclassify", r.getUserId());
+ applyAdjustmentLocked(r, adj, isPosted);
+ mRankingHandler.requestSort();
+ } else {
+ if (DBG) {
+ Slog.w(TAG, "Can't reclassify. No valid bundle type or already bundled: " + r);
+ }
+ }
+ }
NotificationManagerPrivate mNotificationManagerPrivate = new NotificationManagerPrivate() {
@Nullable
@@ -4370,7 +4484,11 @@ public class NotificationManagerService extends SystemService {
public void allowAssistantAdjustment(String adjustmentType) {
checkCallerIsSystemOrSystemUiOrShell();
mAssistants.allowAdjustmentType(adjustmentType);
-
+ if ((notificationClassificationUi() && notificationRegroupOnClassification())) {
+ if (KEY_TYPE.equals(adjustmentType)) {
+ reclassifyNotificationsForUser(UserHandle.getUserId(Binder.getCallingUid()));
+ }
+ }
handleSavePolicyFile();
}
@@ -4379,7 +4497,11 @@ public class NotificationManagerService extends SystemService {
public void disallowAssistantAdjustment(String adjustmentType) {
checkCallerIsSystemOrSystemUiOrShell();
mAssistants.disallowAdjustmentType(adjustmentType);
-
+ if ((notificationClassificationUi() && notificationRegroupOnClassification())) {
+ if (KEY_TYPE.equals(adjustmentType)) {
+ unclassifyNotificationsForUser(UserHandle.getUserId(Binder.getCallingUid()));
+ }
+ }
handleSavePolicyFile();
}
@@ -4416,7 +4538,7 @@ public class NotificationManagerService extends SystemService {
@FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
public @NonNull int[] getAllowedAdjustmentKeyTypes() {
checkCallerIsSystemOrSystemUiOrShell();
- return mAssistants.getAllowedAdjustmentKeyTypes();
+ return mAssistants.getAllowedClassificationTypes();
}
@Override
@@ -4424,23 +4546,39 @@ public class NotificationManagerService extends SystemService {
public void setAssistantAdjustmentKeyTypeState(int type, boolean enabled) {
checkCallerIsSystemOrSystemUiOrShell();
mAssistants.setAssistantAdjustmentKeyTypeState(type, enabled);
-
+ if ((notificationClassificationUi() && notificationRegroupOnClassification())) {
+ if (enabled) {
+ reclassifyNotificationsForUserAndType(
+ UserHandle.getUserId(Binder.getCallingUid()), type);
+ } else {
+ unclassifyNotificationsForUserAndType(
+ UserHandle.getUserId(Binder.getCallingUid()), type);
+ }
+ }
handleSavePolicyFile();
}
@Override
- @FlaggedApi(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- public @NonNull String[] getTypeAdjustmentDeniedPackages() {
+ public boolean isAdjustmentSupportedForPackage(String key, String pkg) {
checkCallerIsSystemOrSystemUiOrShell();
- return mAssistants.getTypeAdjustmentDeniedPackages();
+ return mAssistants.isAdjustmentAllowedForPackage(key, pkg);
}
@Override
- @FlaggedApi(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- public void setTypeAdjustmentForPackageState(String pkg, boolean enabled) {
+ public void setAdjustmentSupportedForPackage(@Adjustment.Keys String key, String pkg,
+ boolean enabled) {
checkCallerIsSystemOrSystemUiOrShell();
- mAssistants.setTypeAdjustmentForPackageState(pkg, enabled);
-
+ mAssistants.setAdjustmentSupportedForPackage(key, pkg, enabled);
+ if (notificationClassificationUi() && notificationRegroupOnClassification()
+ && key.equals(KEY_TYPE)) {
+ if (enabled) {
+ reclassifyNotificationsForUid(UserHandle.getUserId(Binder.getCallingUid()),
+ pkg);
+ } else {
+ unclassifyNotificationsForUid(UserHandle.getUserId(Binder.getCallingUid()),
+ pkg);
+ }
+ }
handleSavePolicyFile();
}
@@ -5056,14 +5194,8 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public ParceledListSlice<NotificationChannel> getNotificationChannels(
- String callingPkg, String targetPkg, int userId) {
- return getOrCreateNotificationChannels(callingPkg, targetPkg, userId, false);
- }
-
- @Override
- public ParceledListSlice<NotificationChannel> getOrCreateNotificationChannels(
- String callingPkg, String targetPkg, int userId, boolean createPrefsIfNeeded) {
+ public ParceledListSlice<NotificationChannel> getNotificationChannels(String callingPkg,
+ String targetPkg, int userId) {
if (canNotifyAsPackage(callingPkg, targetPkg, userId)
|| isCallingUidSystem()) {
int targetUid = -1;
@@ -5073,8 +5205,7 @@ public class NotificationManagerService extends SystemService {
/* ignore */
}
return mPreferencesHelper.getNotificationChannels(
- targetPkg, targetUid, false /* includeDeleted */, true,
- createPrefsIfNeeded);
+ targetPkg, targetUid, false /* includeDeleted */, true);
}
throw new SecurityException("Pkg " + callingPkg
+ " cannot read channels for " + targetPkg + " in " + userId);
@@ -7245,6 +7376,10 @@ public class NotificationManagerService extends SystemService {
if (adjustment.getSignals() != null) {
final Bundle adjustments = adjustment.getSignals();
Bundle.setDefusable(adjustments, true);
+ // Save classification even if the adjustment is disabled, in case user enables it later
+ if (notificationClassification() && adjustments.containsKey(KEY_TYPE)) {
+ r.setBundleType(adjustments.getInt(KEY_TYPE));
+ }
List<String> toRemove = new ArrayList<>();
for (String potentialKey : adjustments.keySet()) {
if (!mAssistants.isAdjustmentAllowed(potentialKey)) {
@@ -7255,7 +7390,14 @@ public class NotificationManagerService extends SystemService {
if (!mAssistants.isAdjustmentKeyTypeAllowed(adjustments.getInt(KEY_TYPE))) {
toRemove.add(potentialKey);
} else if (notificationClassificationUi()
- && !mAssistants.isTypeAdjustmentAllowedForPackage(
+ && !mAssistants.isAdjustmentAllowedForPackage(KEY_TYPE,
+ r.getSbn().getPackageName())) {
+ toRemove.add(potentialKey);
+ }
+ }
+ if ((nmSummarization() || nmSummarizationUi())
+ && potentialKey.equals(KEY_SUMMARIZATION)) {
+ if (!mAssistants.isAdjustmentAllowedForPackage(KEY_SUMMARIZATION,
r.getSbn().getPackageName())) {
toRemove.add(potentialKey);
}
@@ -7274,9 +7416,7 @@ public class NotificationManagerService extends SystemService {
int classification = adjustments.getInt(KEY_TYPE);
// swap app provided type with the real thing
adjustments.putParcelable(KEY_TYPE, newChannel);
-
logClassificationChannelAdjustmentReceived(r, isPosted, classification);
- r.setBundleType(classification);
}
}
r.addAdjustment(adjustment);
@@ -8505,6 +8645,9 @@ public class NotificationManagerService extends SystemService {
(userId == USER_ALL) ? USER_SYSTEM : userId);
Notification.addFieldsFromContext(ai, notification);
+ // can't be set by an app
+ notification.extras.remove(Notification.EXTRA_SUMMARIZED_CONTENT);
+
if (notification.isForegroundService() && fgsPolicy == NOT_FOREGROUND_SERVICE) {
notification.flags &= ~FLAG_FOREGROUND_SERVICE;
}
@@ -8755,7 +8898,7 @@ public class NotificationManagerService extends SystemService {
if (contentView == null) {
return false;
}
- final int contentViewSize = contentView.estimateMemoryUsage();
+ final long contentViewSize = contentView.estimateMemoryUsage();
if (contentViewSize > mWarnRemoteViewsSizeBytes
&& contentViewSize < mStripRemoteViewsSizeBytes) {
Slog.w(TAG, "RemoteViews too large on pkg: " + pkg + " tag: " + tag + " id: " + id
@@ -11907,15 +12050,17 @@ public class NotificationManagerService extends SystemService {
static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
private static final String ATT_TYPES = "types";
- private static final String ATT_DENIED = "user_denied_adjustments";
- private static final String ATT_ENABLED_TYPES = "enabled_key_types";
+ private static final String TAG_DENIED = "user_denied_adjustments";
+ private static final String TAG_DENIED_KEY = "adjustment";
+ private static final String ATT_DENIED_KEY = "key";
+ private static final String ATT_DENIED_KEY_APPS = "denied_apps";
+ private static final String TAG_ENABLED_TYPES = "enabled_key_types";
private static final String ATT_NAS_UNSUPPORTED = "nas_unsupported_adjustments";
- private static final String ATT_TYPES_DENIED_APPS = "types_denied_apps";
private final Object mLock = new Object();
@GuardedBy("mLock")
- private Set<Integer> mAllowedAdjustmentKeyTypes = new ArraySet<>();
+ private Set<Integer> mAllowedClassificationTypes = new ArraySet<>();
@GuardedBy("mLock")
private Set<String> mAllowedAdjustments = new ArraySet<>();
@@ -11926,8 +12071,10 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mLock")
private Map<Integer, HashSet<String>> mNasUnsupported = new ArrayMap<>();
+ // key: Adjustment key. value - list of pkgs that we shouldn't apply adjustments with that
+ // key to
@GuardedBy("mLock")
- private Set<String> mClassificationTypeDeniedPackages = new ArraySet<>();
+ private Map<String, Set<String>> mAdjustmentKeyDeniedPackages = new ArrayMap<>();
protected ComponentName mDefaultFromConfig = null;
@@ -12004,7 +12151,7 @@ public class NotificationManagerService extends SystemService {
mAllowedAdjustments.add(DEFAULT_ALLOWED_ADJUSTMENTS[i]);
}
} else {
- mAllowedAdjustmentKeyTypes.addAll(List.of(DEFAULT_ALLOWED_ADJUSTMENT_KEY_TYPES));
+ mAllowedClassificationTypes.addAll(List.of(DEFAULT_ALLOWED_ADJUSTMENT_KEY_TYPES));
}
}
@@ -12096,17 +12243,17 @@ public class NotificationManagerService extends SystemService {
protected @NonNull boolean isAdjustmentKeyTypeAllowed(@Adjustment.Types int type) {
synchronized (mLock) {
if (notificationClassification()) {
- return mAllowedAdjustmentKeyTypes.contains(type);
+ return mAllowedClassificationTypes.contains(type);
}
}
return false;
}
@FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
- protected @NonNull int[] getAllowedAdjustmentKeyTypes() {
+ protected @NonNull int[] getAllowedClassificationTypes() {
synchronized (mLock) {
if (notificationClassification()) {
- return mAllowedAdjustmentKeyTypes.stream()
+ return mAllowedClassificationTypes.stream()
.mapToInt(Integer::intValue).toArray();
}
}
@@ -12121,47 +12268,35 @@ public class NotificationManagerService extends SystemService {
}
synchronized (mLock) {
if (enabled) {
- mAllowedAdjustmentKeyTypes.add(type);
+ mAllowedClassificationTypes.add(type);
} else {
- mAllowedAdjustmentKeyTypes.remove(type);
+ mAllowedClassificationTypes.remove(type);
}
}
}
- @FlaggedApi(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- protected @NonNull boolean isTypeAdjustmentAllowedForPackage(String pkg) {
+ protected @NonNull boolean isAdjustmentAllowedForPackage(@Adjustment.Keys String key,
+ String pkg) {
synchronized (mLock) {
- if (notificationClassificationUi()) {
- return !mClassificationTypeDeniedPackages.contains(pkg);
+ if (notificationClassificationUi() || nmSummarization() | nmSummarizationUi()) {
+ return !mAdjustmentKeyDeniedPackages.getOrDefault(
+ key, new ArraySet<>()).contains(pkg);
}
}
return true;
}
- @FlaggedApi(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- protected @NonNull String[] getTypeAdjustmentDeniedPackages() {
- synchronized (mLock) {
- if (notificationClassificationUi()) {
- return mClassificationTypeDeniedPackages.toArray(new String[0]);
- }
- }
- return new String[]{};
- }
-
- /**
- * Set whether a particular package can have its notification channels adjusted to have a
- * different type by NotificationAssistants.
- */
- @FlaggedApi(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- public void setTypeAdjustmentForPackageState(String pkg, boolean enabled) {
- if (!notificationClassificationUi()) {
+ public void setAdjustmentSupportedForPackage(@Adjustment.Keys String key, String pkg,
+ boolean enabled) {
+ if (!(notificationClassificationUi() || nmSummarization() | nmSummarizationUi())) {
return;
}
synchronized (mLock) {
+ mAdjustmentKeyDeniedPackages.putIfAbsent(key, new ArraySet<>());
if (enabled) {
- mClassificationTypeDeniedPackages.remove(pkg);
+ mAdjustmentKeyDeniedPackages.get(key).remove(pkg);
} else {
- mClassificationTypeDeniedPackages.add(pkg);
+ mAdjustmentKeyDeniedPackages.get(key).add(pkg);
}
}
}
@@ -12625,32 +12760,35 @@ public class NotificationManagerService extends SystemService {
@Override
protected void writeExtraXmlTags(TypedXmlSerializer out) throws IOException {
- if (!notificationClassification()) {
+ if (!(notificationClassificationUi() || nmSummarization() || nmSummarizationUi())) {
return;
}
synchronized (mLock) {
- out.startTag(null, ATT_DENIED);
+ out.startTag(null, TAG_DENIED);
out.attribute(null, ATT_TYPES, TextUtils.join(",", mDeniedAdjustments));
- out.endTag(null, ATT_DENIED);
- out.startTag(null, ATT_ENABLED_TYPES);
- out.attribute(null, ATT_TYPES,
- TextUtils.join(",", mAllowedAdjustmentKeyTypes));
- out.endTag(null, ATT_ENABLED_TYPES);
- if (notificationClassificationUi()) {
- out.startTag(null, ATT_TYPES_DENIED_APPS);
- out.attribute(null, ATT_TYPES,
- TextUtils.join(",", mClassificationTypeDeniedPackages));
- out.endTag(null, ATT_TYPES_DENIED_APPS);
+ for (String key : mAdjustmentKeyDeniedPackages.keySet()) {
+ Set<String> pkgs = mAdjustmentKeyDeniedPackages.get(key);
+ if (pkgs != null && !pkgs.isEmpty()) {
+ out.startTag(null, TAG_DENIED_KEY);
+ out.attribute(null, ATT_DENIED_KEY, key);
+ out.attribute(null, ATT_DENIED_KEY_APPS, TextUtils.join(",", pkgs));
+ out.endTag(null, TAG_DENIED_KEY);
+ }
}
+ out.endTag(null, TAG_DENIED);
+ out.startTag(null, TAG_ENABLED_TYPES);
+ out.attribute(null, ATT_TYPES,
+ TextUtils.join(",", mAllowedClassificationTypes));
+ out.endTag(null, TAG_ENABLED_TYPES);
}
}
@Override
protected void readExtraTag(String tag, TypedXmlPullParser parser) throws IOException {
- if (!notificationClassification()) {
+ if (!(notificationClassificationUi() || nmSummarization() || nmSummarizationUi())) {
return;
}
- if (ATT_DENIED.equals(tag)) {
+ if (TAG_DENIED.equals(tag)) {
final String keys = XmlUtils.readStringAttribute(parser, ATT_TYPES);
synchronized (mLock) {
mDeniedAdjustments.clear();
@@ -12658,28 +12796,27 @@ public class NotificationManagerService extends SystemService {
mDeniedAdjustments.addAll(Arrays.asList(keys.split(",")));
}
}
- } else if (ATT_ENABLED_TYPES.equals(tag)) {
+ } else if (TAG_ENABLED_TYPES.equals(tag)) {
final String types = XmlUtils.readStringAttribute(parser, ATT_TYPES);
synchronized (mLock) {
- mAllowedAdjustmentKeyTypes.clear();
+ mAllowedClassificationTypes.clear();
if (!TextUtils.isEmpty(types)) {
List<String> typeList = Arrays.asList(types.split(","));
for (String type : typeList) {
try {
- mAllowedAdjustmentKeyTypes.add(Integer.parseInt(type));
+ mAllowedClassificationTypes.add(Integer.parseInt(type));
} catch (NumberFormatException e) {
Slog.wtf(TAG, "Bad type specified", e);
}
}
}
}
- } else if (notificationClassificationUi() && ATT_TYPES_DENIED_APPS.equals(tag)) {
- final String apps = XmlUtils.readStringAttribute(parser, ATT_TYPES);
- synchronized (mLock) {
- mClassificationTypeDeniedPackages.clear();
- if (!TextUtils.isEmpty(apps)) {
- mClassificationTypeDeniedPackages.addAll(Arrays.asList(apps.split(",")));
- }
+ } else if (TAG_DENIED_KEY.equals(tag)) {
+ final String key = XmlUtils.readStringAttribute(parser, ATT_DENIED_KEY);
+ final String pkgs = XmlUtils.readStringAttribute(parser, ATT_DENIED_KEY_APPS);
+ if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(pkgs)) {
+ List<String> pkgList = Arrays.asList(pkgs.split(","));
+ mAdjustmentKeyDeniedPackages.put(key, new ArraySet<>(pkgList));
}
}
}
@@ -12708,7 +12845,7 @@ public class NotificationManagerService extends SystemService {
bundlesAllowed = !unsupportedAdjustments.contains(Adjustment.KEY_TYPE);
}
- int[] allowedBundleTypes = getAllowedAdjustmentKeyTypes();
+ int[] allowedBundleTypes = getAllowedClassificationTypes();
events.add(FrameworkStatsLog.buildStatsEvent(
NOTIFICATION_BUNDLE_PREFERENCES,
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 52101e336920..1def7ec1753b 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -473,10 +473,6 @@ public final class NotificationRecord {
}
}
- if (android.service.notification.Flags.notificationClassification()) {
- mBundleType = previous.mBundleType;
- }
-
// Don't copy importance information or mGlobalSortKey, recompute them.
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 3b34dcd17705..7d45cd9752b8 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -16,8 +16,8 @@
package com.android.server.notification;
-import static android.app.Flags.notificationClassificationUi;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.Flags.notificationClassificationUi;
import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
import static android.app.NotificationChannel.NEWS_ID;
import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
@@ -34,10 +34,6 @@ import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.os.UserHandle.USER_SYSTEM;
-import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION;
-import static android.service.notification.Adjustment.TYPE_NEWS;
-import static android.service.notification.Adjustment.TYPE_PROMOTION;
-import static android.service.notification.Adjustment.TYPE_SOCIAL_MEDIA;
import static android.service.notification.Flags.notificationClassification;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
@@ -89,9 +85,10 @@ import android.util.SparseBooleanArray;
import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags;
import com.android.internal.logging.MetricsLogger;
@@ -1427,20 +1424,6 @@ public class PreferencesHelper implements RankingConfig {
}
}
- private @Nullable String getChannelIdForBundleType(@Adjustment.Types int type) {
- switch (type) {
- case TYPE_CONTENT_RECOMMENDATION:
- return RECS_ID;
- case TYPE_NEWS:
- return NEWS_ID;
- case TYPE_PROMOTION:
- return PROMOTIONS_ID;
- case TYPE_SOCIAL_MEDIA:
- return SOCIAL_MEDIA_ID;
- }
- return null;
- }
-
@FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
public NotificationChannel getReservedChannel(String pkg, int uid,
@Adjustment.Types int type) {
@@ -1448,7 +1431,7 @@ public class PreferencesHelper implements RankingConfig {
return null;
}
Objects.requireNonNull(pkg);
- String channelId = getChannelIdForBundleType(type);
+ String channelId = NotificationChannel.getChannelIdForBundleType(type);
if (channelId == null) {
return null;
}
@@ -1468,7 +1451,7 @@ public class PreferencesHelper implements RankingConfig {
if (r == null) {
return null;
}
- String channelId = getChannelIdForBundleType(type);
+ String channelId = NotificationChannel.getChannelIdForBundleType(type);
if (channelId == null) {
return null;
}
@@ -1962,21 +1945,11 @@ public class PreferencesHelper implements RankingConfig {
@Override
public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
boolean includeDeleted, boolean includeBundles) {
- return getNotificationChannels(pkg, uid, includeDeleted, includeBundles, false);
- }
-
- protected ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
- boolean includeDeleted, boolean includeBundles, boolean createPrefsIfNeeded) {
- if (createPrefsIfNeeded && !android.app.Flags.nmBinderPerfCacheChannels()) {
- Slog.wtf(TAG,
- "getNotificationChannels called with createPrefsIfNeeded=true and flag off");
- createPrefsIfNeeded = false;
- }
Objects.requireNonNull(pkg);
List<NotificationChannel> channels = new ArrayList<>();
synchronized (mLock) {
PackagePreferences r;
- if (createPrefsIfNeeded) {
+ if (android.app.Flags.nmBinderPerfCacheChannels()) {
r = getOrCreatePackagePreferencesLocked(pkg, uid);
} else {
r = getPackagePreferencesLocked(pkg, uid);
@@ -1997,6 +1970,18 @@ public class PreferencesHelper implements RankingConfig {
}
}
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ // Gets the entire list of notification channels for this package, with no filtering and
+ // without creating package preferences. For testing only, specifically to confirm the
+ // notification channels of a removed/deleted package.
+ protected List<NotificationChannel> getRemovedPkgNotificationChannels(String pkg, int uid) {
+ PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
+ if (r == null || r.channels == null) {
+ return new ArrayList<>();
+ }
+ return new ArrayList<>(r.channels.values());
+ }
+
/**
* Gets all notification channels associated with the given pkg and uid that can bypass dnd
*/
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index b8b49f3eed2f..f9758fcd5d01 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -26,13 +26,13 @@ import android.content.om.OverlayInfo;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Pair;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -49,7 +49,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
-import java.util.stream.Stream;
/**
* Data structure representing the current state of all overlay packages in the
@@ -358,26 +357,29 @@ final class OverlayManagerSettings {
}
void dump(@NonNull final PrintWriter p, @NonNull DumpState dumpState) {
- // select items to display
- Stream<SettingsItem> items = mItems.stream();
- if (dumpState.getUserId() != UserHandle.USER_ALL) {
- items = items.filter(item -> item.mUserId == dumpState.getUserId());
- }
- if (dumpState.getPackageName() != null) {
- items = items.filter(item -> item.mOverlay.getPackageName()
- .equals(dumpState.getPackageName()));
- }
- if (dumpState.getOverlayName() != null) {
- items = items.filter(item -> item.mOverlay.getOverlayName()
- .equals(dumpState.getOverlayName()));
- }
-
- // display items
- final IndentingPrintWriter pw = new IndentingPrintWriter(p, " ");
- if (dumpState.getField() != null) {
- items.forEach(item -> dumpSettingsItemField(pw, item, dumpState.getField()));
- } else {
- items.forEach(item -> dumpSettingsItem(pw, item));
+ final int userId = dumpState.getUserId();
+ final String packageName = dumpState.getPackageName();
+ final String overlayName = dumpState.getOverlayName();
+ final String field = dumpState.getField();
+ final var pw = new IndentingPrintWriter(p, " ");
+
+ for (int i = 0; i < mItems.size(); i++) {
+ final var item = mItems.get(i);
+ if (userId != UserHandle.USER_ALL && userId != item.mUserId) {
+ continue;
+ }
+ if (packageName != null && !packageName.equals(item.mOverlay.getPackageName())) {
+ continue;
+ }
+ if (overlayName != null && !overlayName.equals(item.mOverlay.getOverlayName())) {
+ continue;
+ }
+
+ if (field != null) {
+ dumpSettingsItemField(pw, item, field);
+ } else {
+ dumpSettingsItem(pw, item);
+ }
}
}
diff --git a/services/core/java/com/android/server/pinner/PinnerService.java b/services/core/java/com/android/server/pinner/PinnerService.java
index 2c75926c4943..5ed268819961 100644
--- a/services/core/java/com/android/server/pinner/PinnerService.java
+++ b/services/core/java/com/android/server/pinner/PinnerService.java
@@ -1305,11 +1305,13 @@ public final class PinnerService extends SystemService {
mConfiguredMaxPinnedMemoryPercentage);
pw.format(" Maximum Pinner quota: %d bytes (%.2f MB)\n", mConfiguredMaxPinnedMemory,
mConfiguredMaxPinnedMemory / bytesPerMB);
- pw.format(" Max Home App Pin Bytes (without deps): %d\n", mConfiguredHomePinBytes);
- pw.format(" Max Assistant App Pin Bytes (without deps): %d\n",
- mConfiguredAssistantPinBytes);
+ pw.format(" Max Home App Pin Bytes (without deps): %d (%.2f MB)\n",
+ mConfiguredHomePinBytes, mConfiguredHomePinBytes / bytesPerMB);
+ pw.format(" Max Assistant App Pin Bytes (without deps): %d (%.2f MB)\n",
+ mConfiguredAssistantPinBytes, mConfiguredAssistantPinBytes / bytesPerMB);
pw.format(
- " Max Camera App Pin Bytes (without deps): %d\n", mConfiguredCameraPinBytes);
+ " Max Camera App Pin Bytes (without deps): %d (%.2f MB)\n",
+ mConfiguredCameraPinBytes, mConfiguredCameraPinBytes / bytesPerMB);
pw.format("\nPinned Files:\n");
synchronized (PinnerService.this) {
long totalSize = 0;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 283979483e73..4860b7cdfcd3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -239,6 +239,7 @@ import com.android.internal.policy.TransitionAnimation;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.AccessibilityManagerInternal;
+import com.android.server.DockObserverInternal;
import com.android.server.ExtconStateObserver;
import com.android.server.ExtconUEventObserver;
import com.android.server.GestureLauncherService;
@@ -473,6 +474,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
DisplayManager mDisplayManager;
DisplayManagerInternal mDisplayManagerInternal;
UserManagerInternal mUserManagerInternal;
+ DockObserverInternal mDockObserverInternal;
private WallpaperManagerInternal mWallpaperManagerInternal;
@@ -2452,12 +2454,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
filter.addAction(Intent.ACTION_DOCK_EVENT);
- Intent intent = mContext.registerReceiver(mDockReceiver, filter);
- if (intent != null) {
- // Retrieve current sticky dock event broadcast.
- mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED));
- }
+ mContext.registerReceiver(mDockReceiver, filter);
// register for multiuser-relevant broadcasts
filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
@@ -3667,7 +3664,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
break;
case KeyEvent.KEYCODE_S:
- if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
+ if (firstDown && event.isMetaPressed()) {
interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT);
@@ -6756,6 +6753,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
}
+ mDockObserverInternal = LocalServices.getService(DockObserverInternal.class);
+ if (mDockObserverInternal != null) {
+ // Get initial state from DockObserverInternal, DockObserver starts after WM.
+ int dockMode = mDockObserverInternal.getActualDockState();
+ mDefaultDisplayPolicy.setDockMode(dockMode);
+ }
+
readCameraLensCoverState();
updateUiMode();
mDefaultDisplayRotation.updateOrientationListener();
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 977c6db66106..a5185a2139db 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -38,6 +38,7 @@ import com.android.internal.os.CpuScalingPolicies;
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerProfile;
import com.android.internal.util.ArrayUtils;
+import com.android.server.power.optimization.Flags;
import com.android.server.power.stats.BatteryStatsImpl.BatteryStatsSession;
import java.io.PrintWriter;
@@ -351,7 +352,7 @@ public class BatteryUsageStatsProvider {
accumulatedStats.endMonotonicTime = endMonotonicTime;
accumulatedStats.builder.setStatsEndTimestamp(endWallClockTime);
- accumulatedStats.builder.setStatsDuration(endWallClockTime - startMonotonicTime);
+ accumulatedStats.builder.setStatsDuration(endMonotonicTime - startMonotonicTime);
mPowerAttributor.estimatePowerConsumption(accumulatedStats.builder, session.getHistory(),
startMonotonicTime, endMonotonicTime);
@@ -403,7 +404,10 @@ public class BatteryUsageStatsProvider {
}
if ((query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY) != 0) {
- batteryUsageStatsBuilder.setBatteryHistory(session.getHistory().copy());
+ batteryUsageStatsBuilder.setBatteryHistory(session.getHistory().copy(),
+ Flags.extendedBatteryHistoryContinuousCollectionEnabled()
+ ? query.getPreferredHistoryDurationMs()
+ : Long.MAX_VALUE);
}
mPowerAttributor.estimatePowerConsumption(batteryUsageStatsBuilder, session.getHistory(),
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 37056a4af250..e753f273eb9b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -2241,33 +2241,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
}
- /**
- * Called when the notification should be unbundled.
- * @param key the notification key
- */
- @Override
- public void unbundleNotification(@Nullable String key) {
- enforceStatusBarService();
- enforceValidCallingUser();
- Binder.withCleanCallingIdentity(() -> {
- mNotificationDelegate.unbundleNotification(key);
- });
- }
-
- /**
- * Called when the notification should be rebundled.
- * @param key the notification key
- */
- @Override
- public void rebundleNotification(String key) {
- enforceStatusBarService();
- enforceValidCallingUser();
- Binder.withCleanCallingIdentity(() -> {
- mNotificationDelegate.rebundleNotification(key);
- });
- }
-
-
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 064ef1aa0eff..89b46bc4eba4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -46,6 +46,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.isFloating;
import static android.app.admin.DevicePolicyResources.Drawables.Source.PROFILE_SWITCH_ANIMATION;
import static android.app.admin.DevicePolicyResources.Drawables.Style.OUTLINE;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
@@ -8376,6 +8377,7 @@ final class ActivityRecord extends WindowToken {
mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
getResolvedOverrideConfiguration().seq = mConfigurationSeq;
+ // TODO(b/392069771): Move to AppCompatSandboxingPolicy.
// Sandbox max bounds by setting it to the activity bounds, if activity is letterboxed, or
// has or will have mAppCompatDisplayInsets for size compat. Also forces an activity to be
// sandboxed or not depending upon the configuration settings.
@@ -8404,6 +8406,20 @@ final class ActivityRecord extends WindowToken {
resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
}
+ // Sandbox activity bounds in freeform to app bounds to force app to display within the
+ // container. This prevents UI cropping when activities can draw below insets which are
+ // normally excluded from appBounds before targetSDK < 35
+ // (see ConfigurationContainer#applySizeOverrideIfNeeded).
+ if (isFloating(parentWindowingMode)) {
+ Rect appBounds = resolvedConfig.windowConfiguration.getAppBounds();
+ if (appBounds == null || appBounds.isEmpty()) {
+ // When there is no override bounds, the activity will inherit the bounds from
+ // parent.
+ appBounds = mResolveConfigHint.mParentAppBoundsOverride;
+ }
+ resolvedConfig.windowConfiguration.setBounds(appBounds);
+ }
+
applySizeOverrideIfNeeded(
mDisplayContent,
info.applicationInfo,
diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
index 35fa39dab900..d994a1904a14 100644
--- a/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
@@ -180,10 +180,7 @@ class AppCompatOrientationPolicy {
return true;
}
- final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy
- .getAppCompatCameraPolicy(mActivityRecord);
- if (cameraPolicy != null
- && cameraPolicy.isTreatmentEnabledForActivity(mActivityRecord)) {
+ if (AppCompatCameraPolicy.isTreatmentEnabledForActivity(mActivityRecord)) {
Slog.w(TAG, "Ignoring orientation update to "
+ screenOrientationToString(requestedOrientation)
+ " due to camera compat treatment for " + mActivityRecord);
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index 4b30a43db5d9..9d9c5ceb57d6 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
@@ -164,7 +165,8 @@ public abstract class DisplayAreaPolicy {
FEATURE_APP_ZOOM_OUT)
.all()
.except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL,
- TYPE_STATUS_BAR, TYPE_NOTIFICATION_SHADE, TYPE_WALLPAPER)
+ TYPE_STATUS_BAR, TYPE_NOTIFICATION_SHADE,
+ TYPE_KEYGUARD_DIALOG, TYPE_WALLPAPER)
.build());
}
if (USE_DISPLAY_AREA_FOR_FULLSCREEN_MAGNIFICATION) {
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index f465c95addb7..4bcba13448e9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -899,9 +899,7 @@ class InsetsPolicy {
}
@Override
- public void notifyAnimationRunningStateChanged(boolean running,
- @InsetsController.AnimationType int animationType,
- @InsetsType int insetsTypes) {
+ public void notifyAnimationRunningStateChanged(boolean running) {
mInsetsAnimationRunning = running;
}
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index e2b5c839fb0d..abd26b5164f7 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -138,6 +138,7 @@ import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.window.DesktopModeFlags;
import android.window.TaskFragmentAnimationParams;
import android.window.WindowContainerToken;
@@ -1908,7 +1909,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// appropriate.
removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);
- if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
+ if (DesktopModeFlags.ENABLE_TOP_VISIBLE_ROOT_TASK_PER_USER_TRACKING.isTrue()) {
final IntArray visibleRootTasks = new IntArray();
forAllRootTasks(rootTask -> {
if ((mCurrentUser == rootTask.mUserId || rootTask.showForAllUsers())
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index e761e024b3ca..883d8f95b612 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1680,26 +1680,27 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* Sets the specified orientation of this container. It percolates this change upward along the
* hierarchy to let each level of the hierarchy a chance to respond to it.
*
- * @param orientation the specified orientation. Needs to be one of {@link ScreenOrientation}.
+ * @param requestedOrientation the specified orientation. Needs to be one of
+ * {@link ScreenOrientation}.
* @param requestingContainer the container which orientation request has changed. Mostly used
* to ensure it gets correct configuration.
* @return the resolved override orientation of this window container.
*/
@ScreenOrientation
- int setOrientation(@ScreenOrientation int orientation,
+ int setOrientation(@ScreenOrientation int requestedOrientation,
@Nullable WindowContainer requestingContainer) {
- if (getOverrideOrientation() == orientation) {
- return orientation;
+ if (getOverrideOrientation() == requestedOrientation) {
+ return requestedOrientation;
}
- setOverrideOrientation(orientation);
+ setOverrideOrientation(requestedOrientation);
final WindowContainer parent = getParent();
if (parent == null) {
- return orientation;
+ return requestedOrientation;
}
// The derived class can return a result that is different from the given orientation.
- final int resolvedOrientation = getOverrideOrientation();
+ final int actualOverrideOrientation = getOverrideOrientation();
if (getConfiguration().orientation != getRequestedConfigurationOrientation(
- false /* forDisplay */, resolvedOrientation)
+ false /* forDisplay */, actualOverrideOrientation)
// Update configuration directly only if the change won't be dispatched from
// ancestor. This prevents from computing intermediate configuration when the
// parent also needs to be updated from the ancestor. E.g. the app requests
@@ -1707,12 +1708,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// the task can be updated to portrait first so the configuration can be
// computed in a consistent environment.
&& (inMultiWindowMode()
- || !handlesOrientationChangeFromDescendant(orientation))) {
+ || !handlesOrientationChangeFromDescendant(requestedOrientation))) {
// Resolve the requested orientation.
onConfigurationChanged(parent.getConfiguration());
}
onDescendantOrientationChanged(requestingContainer);
- return resolvedOrientation;
+ return actualOverrideOrientation;
}
@ScreenOrientation
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 7a8230f1f963..c77b1d9a7bcf 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -41,7 +41,6 @@ import android.view.Display;
import android.view.IInputFilter;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IWindow;
-import android.view.InsetsController;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationTarget;
import android.view.Surface;
@@ -470,24 +469,6 @@ public abstract class WindowManagerInternal {
public abstract void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion);
/**
- * Set by the autofill service to observe changes in the ime animations.
- *
- * @param listener The callbacks to invoke.
- */
- public abstract void setImeInsetsAnimationChangeListener(
- @Nullable ImeInsetsAnimationChangeListener listener);
-
- /** Listener for changes in ime insets animation */
- public interface ImeInsetsAnimationChangeListener {
-
- /** Notify on start of animation */
- void onAnimationStart(@InsetsController.AnimationType int animationType, int userId);
-
- /** Notify on end of animation */
- void onAnimationEnd(@InsetsController.AnimationType int animationType, int userId);
- }
-
- /**
* Sets a callback for observing which windows are touchable for the purposes
* of accessibility on specified display.
*
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 28ea3b0bf6ba..3a1d652f82d4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.service.autofill.Flags.improveFillDialogAconfig;
import static android.Manifest.permission.ACCESS_SURFACE_FLINGER;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.INPUT_CONSUMER;
@@ -278,7 +277,6 @@ import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputWindowHandle;
-import android.view.InsetsController;
import android.view.InsetsFrameProvider;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
@@ -795,9 +793,6 @@ public class WindowManagerService extends IWindowManager.Stub
final TrustedPresentationListenerController mTrustedPresentationListenerController =
new TrustedPresentationListenerController();
- private WindowManagerInternal.ImeInsetsAnimationChangeListener
- mImeInsetsAnimationChangeListener;
-
@VisibleForTesting
final class SettingsObserver extends ContentObserver {
private final Uri mDisplayInversionEnabledUri =
@@ -8627,14 +8622,6 @@ public class WindowManagerService extends IWindowManager.Stub
// WMS.takeAssistScreenshot takes care of the locking.
return WindowManagerService.this.takeAssistScreenshot(windowTypesToExclude);
}
-
- @Override
- public void setImeInsetsAnimationChangeListener(
- @Nullable WindowManagerInternal.ImeInsetsAnimationChangeListener listener) {
- synchronized (mGlobalLock) {
- mImeInsetsAnimationChangeListener = listener;
- }
- }
}
private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy {
@@ -10192,24 +10179,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- @Override
- public void notifyImeInsetsAnimationStateChanged(
- boolean running, @InsetsController.AnimationType int animationType) {
- if (improveFillDialogAconfig()) {
- synchronized (mGlobalLock) {
- if (mImeInsetsAnimationChangeListener == null) {
- return;
- }
- if (running) {
- mImeInsetsAnimationChangeListener.onAnimationStart(
- animationType, mCurrentUserId);
- } else {
- mImeInsetsAnimationChangeListener.onAnimationEnd(animationType, mCurrentUserId);
- }
- }
- }
- }
-
boolean getDisableSecureWindows() {
return mDisableSecureWindows;
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index a1755e4d9d3b..060f2e803ec9 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -756,40 +756,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
t.getTaskFragmentOrganizer());
}
}
- // Queue-up bounds-change transactions for tasks which are now organized. Do
- // this after hierarchy ops so we have the final organized state.
- entries = t.getChanges().entrySet().iterator();
- while (entries.hasNext()) {
- final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
- final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
- if (wc == null || !wc.isAttached()) {
- Slog.e(TAG, "Attempt to operate on detached container: " + wc);
- continue;
- }
- final Task task = wc.asTask();
- final Rect surfaceBounds = entry.getValue().getBoundsChangeSurfaceBounds();
- if (task == null || !task.isAttached() || surfaceBounds == null) {
- continue;
- }
- if (!task.isOrganized()) {
- final Task parent = task.getParent() != null ? task.getParent().asTask() : null;
- // Also allow direct children of created-by-organizer tasks to be
- // controlled. In the future, these will become organized anyways.
- if (parent == null || !parent.mCreatedByOrganizer) {
- throw new IllegalArgumentException(
- "Can't manipulate non-organized task surface " + task);
- }
- }
- final SurfaceControl.Transaction sft = new SurfaceControl.Transaction();
- final SurfaceControl sc = task.getSurfaceControl();
- sft.setPosition(sc, surfaceBounds.left, surfaceBounds.top);
- if (surfaceBounds.isEmpty()) {
- sft.setWindowCrop(sc, null);
- } else {
- sft.setWindowCrop(sc, surfaceBounds.width(), surfaceBounds.height());
- }
- task.setMainWindowSizeChangeTransaction(sft);
- }
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */);
mService.mTaskSupervisor.endDeferResume();
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 2e126f1b50ba..014f0a2229c1 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -204,7 +204,7 @@ public final class CredentialManagerService
@SuppressWarnings("GuardedBy") // ErrorProne requires service.mLock which is the same
// this.mLock
protected void handlePackageRemovedMultiModeLocked(String packageName, int userId) {
- updateProvidersWhenPackageRemoved(new SettingsWrapper(mContext), packageName);
+ updateProvidersWhenPackageRemoved(new SettingsWrapper(mContext), packageName, userId);
List<CredentialManagerServiceImpl> services = peekServiceListForUserLocked(userId);
if (services == null) {
@@ -234,6 +234,47 @@ public final class CredentialManagerService
}
@GuardedBy("mLock")
+ @SuppressWarnings("GuardedBy") // ErrorProne requires service.mLock which is the same
+ // this.mLock
+ protected void handleServiceRemovedMultiModeLocked(ComponentName componentName, int userId) {
+ updateProvidersWhenServiceRemoved(new SettingsWrapper(mContext), componentName, userId);
+
+ List<CredentialManagerServiceImpl> services = peekServiceListForUserLocked(userId);
+ if (services == null) {
+ return;
+ }
+
+ List<CredentialManagerServiceImpl> servicesToBeRemoved = new ArrayList<>();
+ for (CredentialManagerServiceImpl service : services) {
+ if (service != null) {
+ CredentialProviderInfo credentialProviderInfo = service.getCredentialProviderInfo();
+ ComponentName serviceComponentName =
+ credentialProviderInfo.getServiceInfo().getComponentName();
+ if (serviceComponentName != null && serviceComponentName.equals(componentName)) {
+ servicesToBeRemoved.add(service);
+ }
+ }
+ }
+
+ removeServicesLocked(servicesToBeRemoved, userId);
+ }
+
+ @GuardedBy("mLock")
+ @SuppressWarnings("GuardedBy") // ErrorProne requires service.mLock which is the same
+ // this.mLock
+ private void removeServicesLocked(
+ List<CredentialManagerServiceImpl> servicesToBeRemoved, int userId) {
+ // Iterate over all the services to be removed, and remove them from the user configurable
+ // services cache, the system services cache as well as the setting key-value pair.
+ for (CredentialManagerServiceImpl serviceToBeRemoved : servicesToBeRemoved) {
+ removeServiceFromCache(serviceToBeRemoved, userId);
+ removeServiceFromSystemServicesCache(serviceToBeRemoved, userId);
+ CredentialDescriptionRegistry.forUser(userId)
+ .evictProviderWithPackageName(serviceToBeRemoved.getServicePackageName());
+ }
+ }
+
+ @GuardedBy("mLock")
private void removeServiceFromSystemServicesCache(
CredentialManagerServiceImpl serviceToBeRemoved, int userId) {
if (mSystemServicesCacheList.get(userId) != null) {
@@ -1136,76 +1177,211 @@ public final class CredentialManagerService
}
}
- /** Updates the list of providers when an app is uninstalled. */
- public static void updateProvidersWhenPackageRemoved(
- SettingsWrapper settingsWrapper, String packageName) {
- Slog.i(TAG, "updateProvidersWhenPackageRemoved");
+ /** Updates the list of providers when a particular service within an app is to be removed. */
+ public static void updateProvidersWhenServiceRemoved(
+ SettingsWrapper settingsWrapper, ComponentName componentName, int userId) {
+ Slog.i(TAG, "updateProvidersWhenServiceRemoved for: "
+ + componentName.flattenToString());
- // Get the current providers.
- String rawProviders =
+ // Get the current primary providers.
+ String rawPrimaryProviders =
settingsWrapper.getStringForUser(
- Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, UserHandle.myUserId());
- if (rawProviders == null) {
- Slog.w(TAG, "settings key is null");
- return;
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, userId);
+ if (TextUtils.isEmpty(rawPrimaryProviders)) {
+ Slog.w(TAG, "primary settings key is null");
+ } else {
+ // Remove any service from the primary setting that matches with the service
+ // being removed, and set the filtered list back to the settings key.
+ Set<String> filteredPrimaryProviders = getStoredProvidersExceptService(
+ rawPrimaryProviders, componentName);
+
+ // If there are no more primary providers AND there is no autofill provider either,
+ // that means all providers must be cleared as that is what the Settings UI app
+ // displays to the user.If the autofill provider is present then UI shows that as the
+ // preferred service and other credential provider services can continue to work.
+ if (filteredPrimaryProviders.isEmpty()
+ && !isAutofillProviderPresent(settingsWrapper, userId)) {
+ Slog.d(TAG, "Clearing all credential providers");
+ if (clearAllCredentialProviders(settingsWrapper, userId)) {
+ return;
+ }
+ Slog.e(TAG, "Failed to clear all credential providers");
+ }
+
+ // Set the filtered primary providers to the settings key
+ if (!settingsWrapper.putStringForUser(
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+ String.join(":", filteredPrimaryProviders),
+ UserHandle.myUserId(),
+ /* overrideableByRestore= */ true)) {
+ Slog.e(TAG, "Failed to remove primary service: " + componentName);
+ return;
+ }
}
- // Remove any providers from the primary setting that contain the package name
- // being removed.
- Set<String> primaryProviders = getStoredProviders(rawProviders, packageName);
+ // Read the credential providers to remove any reference of the removed service.
+ String rawCredentialProviders =
+ settingsWrapper.getStringForUser(
+ Settings.Secure.CREDENTIAL_SERVICE, UserHandle.myUserId());
+
+ // Remove any provider services that are same as the one being removed.
+ Set<String> filteredCredentialProviders = getStoredProvidersExceptService(
+ rawCredentialProviders, componentName);
if (!settingsWrapper.putStringForUser(
- Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
- String.join(":", primaryProviders),
+ Settings.Secure.CREDENTIAL_SERVICE,
+ String.join(":", filteredCredentialProviders),
UserHandle.myUserId(),
/* overrideableByRestore= */ true)) {
- Slog.e(TAG, "Failed to remove primary package: " + packageName);
- return;
+ Slog.e(TAG, "Failed to remove secondary service: " + componentName);
}
+ }
+ private static boolean isAutofillProviderPresent(SettingsWrapper settingsWrapper, int userId) {
// Read the autofill provider so we don't accidentally erase it.
String autofillProvider =
settingsWrapper.getStringForUser(
- Settings.Secure.AUTOFILL_SERVICE, UserHandle.myUserId());
+ Settings.Secure.AUTOFILL_SERVICE, userId);
+
+ return autofillProvider != null && !autofillProvider.isEmpty()
+ && !isPlaceholderAutofillProvider(autofillProvider, settingsWrapper);
+ }
+
+ private static boolean isPlaceholderAutofillProvider(String autofillProvider,
+ SettingsWrapper settingsWrapper) {
// If there is an autofill provider and it is the credential autofill service indicating
// that the currently selected primary provider does not support autofill
// then we should keep as is
String credentialAutofillService = settingsWrapper.mContext.getResources().getString(
R.string.config_defaultCredentialManagerAutofillService);
- if (autofillProvider != null && primaryProviders.isEmpty() && !TextUtils.equals(
- autofillProvider, credentialAutofillService)) {
- // If the existing autofill provider is from the app being removed
- // then erase the autofill service setting.
- ComponentName cn = ComponentName.unflattenFromString(autofillProvider);
- if (cn != null && cn.getPackageName().equals(packageName)) {
- if (!settingsWrapper.putStringForUser(
- Settings.Secure.AUTOFILL_SERVICE,
- "",
- UserHandle.myUserId(),
- /* overrideableByRestore= */ true)) {
- Slog.e(TAG, "Failed to remove autofill package: " + packageName);
+ return autofillProvider != null && TextUtils.equals(
+ autofillProvider, credentialAutofillService);
+ }
+
+ private static boolean clearAllCredentialProviders(SettingsWrapper settingsWrapper,
+ int userId) {
+ if (!settingsWrapper.putStringForUser(
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+ null,
+ userId,
+ /* overrideableByRestore= */ true)) {
+ return false;
+ }
+ return settingsWrapper.putStringForUser(
+ Settings.Secure.CREDENTIAL_SERVICE,
+ null,
+ userId,
+ /* overrideableByRestore= */ true);
+ }
+
+ /** Updates the list of providers when an app is uninstalled. */
+ public static void updateProvidersWhenPackageRemoved(
+ SettingsWrapper settingsWrapper, String packageName, int userId) {
+ Slog.i(TAG, "updateProvidersWhenPackageRemoved");
+
+ // Get the current providers.
+ String rawProviders =
+ settingsWrapper.getStringForUser(
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, userId);
+ if (rawProviders == null) {
+ Slog.w(TAG, "settings key is null");
+ } else {
+ // Remove any providers from the primary setting that contain the package name
+ // being removed.
+ Set<String> primaryProviders = getStoredProvidersExceptPackage(rawProviders,
+ packageName);
+ if (!settingsWrapper.putStringForUser(
+ Settings.Secure.CREDENTIAL_SERVICE_PRIMARY,
+ String.join(":", primaryProviders),
+ userId,
+ /* overrideableByRestore= */ true)) {
+ Slog.e(TAG, "Failed to remove primary package: " + packageName);
+ return;
+ }
+
+ // Read the autofill provider so we don't accidentally erase it.
+ String autofillProvider =
+ settingsWrapper.getStringForUser(
+ Settings.Secure.AUTOFILL_SERVICE, userId);
+
+ // If there is an autofill provider and it is the credential autofill service indicating
+ // that the currently selected primary provider does not support autofill
+ // then we should keep as is
+ String credentialAutofillService = settingsWrapper.mContext.getResources().getString(
+ R.string.config_defaultCredentialManagerAutofillService);
+ if (autofillProvider != null && primaryProviders.isEmpty() && !TextUtils.equals(
+ autofillProvider, credentialAutofillService)) {
+ // If the existing autofill provider is from the app being removed
+ // then erase the autofill service setting.
+ ComponentName cn = ComponentName.unflattenFromString(autofillProvider);
+ if (cn != null && cn.getPackageName().equals(packageName)) {
+ if (!settingsWrapper.putStringForUser(
+ Settings.Secure.AUTOFILL_SERVICE,
+ "",
+ userId,
+ /* overrideableByRestore= */ true)) {
+ Slog.e(TAG, "Failed to remove autofill package: " + packageName);
+ }
}
}
+
+ // If there are no more primary providers AND there is no autofill provider either,
+ // that means all providers must be cleared as that is what the Settings UI app
+ // displays to the user.If the autofill provider is present then UI shows that as the
+ // preferred service and other credential provider services can continue to work.
+ if (primaryProviders.isEmpty() && !isAutofillProviderPresent(settingsWrapper, userId)) {
+ Slog.d(TAG, "Clearing all credential providers");
+ if (clearAllCredentialProviders(settingsWrapper, userId)) {
+ return;
+ }
+ Slog.e(TAG, "Failed to clear all credential providers");
+ }
}
// Read the credential providers to remove any reference of the removed app.
String rawCredentialProviders =
settingsWrapper.getStringForUser(
- Settings.Secure.CREDENTIAL_SERVICE, UserHandle.myUserId());
+ Settings.Secure.CREDENTIAL_SERVICE, userId);
// Remove any providers that belong to the removed app.
- Set<String> credentialProviders = getStoredProviders(rawCredentialProviders, packageName);
+ Set<String> credentialProviders = getStoredProvidersExceptPackage(
+ rawCredentialProviders, packageName);
if (!settingsWrapper.putStringForUser(
Settings.Secure.CREDENTIAL_SERVICE,
String.join(":", credentialProviders),
- UserHandle.myUserId(),
+ userId,
/* overrideableByRestore= */ true)) {
Slog.e(TAG, "Failed to remove secondary package: " + packageName);
}
}
/** Gets the list of stored providers from a string removing any mention of package name. */
- public static Set<String> getStoredProviders(String rawProviders, String packageName) {
+ public static Set<String> getStoredProvidersExceptService(String rawProviders,
+ ComponentName componentName) {
+ // If the app being removed matches any of the package names from
+ // this list then don't add it in the output.
+ Set<String> providers = new HashSet<>();
+ if (rawProviders == null || componentName == null) {
+ return providers;
+ }
+ for (String rawComponentName : rawProviders.split(":")) {
+ if (TextUtils.isEmpty(rawComponentName) || rawComponentName.equals("null")) {
+ Slog.d(TAG, "provider component name is empty or null");
+ continue;
+ }
+
+ ComponentName cn = ComponentName.unflattenFromString(rawComponentName);
+ if (cn != null && !cn.equals(componentName)) {
+ providers.add(cn.flattenToString());
+ }
+ }
+
+ return providers;
+ }
+
+ /** Gets the list of stored providers from a string removing any mention of package name. */
+ public static Set<String> getStoredProvidersExceptPackage(
+ String rawProviders, String packageName) {
// If the app being removed matches any of the package names from
// this list then don't add it in the output.
Set<String> providers = new HashSet<>();
@@ -1213,8 +1389,7 @@ public final class CredentialManagerService
return providers;
}
for (String rawComponentName : rawProviders.split(":")) {
- if (TextUtils.isEmpty(rawComponentName)
- || rawComponentName.equals("null")) {
+ if (TextUtils.isEmpty(rawComponentName) || rawComponentName.equals("null")) {
Slog.d(TAG, "provider component name is empty or null");
continue;
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
index b86db065cfd7..40554ac51b24 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
@@ -57,6 +57,13 @@ public final class CredentialManagerServiceImpl extends
}
}
+ @Nullable
+ @Override
+ @GuardedBy("mLock")
+ public ComponentName getServiceComponentName() {
+ return getComponentName();
+ }
+
@GuardedBy("mLock")
public ComponentName getComponentName() {
return mInfo.getServiceInfo().getComponentName();
diff --git a/services/supervision/java/com/android/server/supervision/SupervisionService.java b/services/supervision/java/com/android/server/supervision/SupervisionService.java
index 073ee31ddd60..ea85710eab44 100644
--- a/services/supervision/java/com/android/server/supervision/SupervisionService.java
+++ b/services/supervision/java/com/android/server/supervision/SupervisionService.java
@@ -23,6 +23,7 @@ import static com.android.internal.util.Preconditions.checkCallAuthorization;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
@@ -51,7 +52,6 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.pm.UserManagerInternal;
import java.io.FileDescriptor;
@@ -62,26 +62,28 @@ import java.util.List;
public class SupervisionService extends ISupervisionManager.Stub {
private static final String LOG_TAG = "SupervisionService";
- private final Context mContext;
-
// TODO(b/362756788): Does this need to be a LockGuard lock?
private final Object mLockDoNoUseDirectly = new Object();
@GuardedBy("getLockObject()")
private final SparseArray<SupervisionUserData> mUserData = new SparseArray<>();
- private final DevicePolicyManagerInternal mDpmInternal;
- private final PackageManager mPackageManager;
- private final UserManagerInternal mUserManagerInternal;
+ private final Context mContext;
+ private final Injector mInjector;
+ final SupervisionManagerInternal mInternal = new SupervisionManagerInternalImpl();
public SupervisionService(Context context) {
mContext = context.createAttributionContext(LOG_TAG);
- mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
- mPackageManager = context.getPackageManager();
- mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
- mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener());
+ mInjector = new Injector(context);
+ mInjector.getUserManagerInternal().addUserLifecycleListener(new UserLifecycleListener());
}
+ /**
+ * Returns whether supervision is enabled for the given user.
+ *
+ * <p>Supervision is automatically enabled when the supervision app becomes the profile owner or
+ * explicitly enabled via an internal call to {@link #setSupervisionEnabledForUser}.
+ */
@Override
public boolean isSupervisionEnabledForUser(@UserIdInt int userId) {
if (UserHandle.getUserId(Binder.getCallingUid()) != userId) {
@@ -93,6 +95,28 @@ public class SupervisionService extends ISupervisionManager.Stub {
}
@Override
+ public void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled) {
+ if (UserHandle.getUserId(Binder.getCallingUid()) != userId) {
+ enforcePermission(INTERACT_ACROSS_USERS);
+ }
+ setSupervisionEnabledForUserInternal(userId, enabled, getSystemSupervisionPackage());
+ }
+
+ /**
+ * Returns the package name of the active supervision app or null if supervision is disabled.
+ */
+ @Override
+ @Nullable
+ public String getActiveSupervisionAppPackage(@UserIdInt int userId) {
+ if (UserHandle.getUserId(Binder.getCallingUid()) != userId) {
+ enforcePermission(INTERACT_ACROSS_USERS);
+ }
+ synchronized (getLockObject()) {
+ return getUserDataLocked(userId).supervisionAppPackage;
+ }
+ }
+
+ @Override
public void onShellCommand(
@Nullable FileDescriptor in,
@Nullable FileDescriptor out,
@@ -114,7 +138,7 @@ public class SupervisionService extends ISupervisionManager.Stub {
pw.println("SupervisionService state:");
pw.increaseIndent();
- List<UserInfo> users = mUserManagerInternal.getUsers(false);
+ List<UserInfo> users = mInjector.getUserManagerInternal().getUsers(false);
synchronized (getLockObject()) {
for (var user : users) {
getUserDataLocked(user.id).dump(pw);
@@ -140,35 +164,54 @@ public class SupervisionService extends ISupervisionManager.Stub {
return data;
}
- void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled) {
+ /**
+ * Sets supervision as enabled or disabled for the given user and, in case supervision is being
+ * enabled, the package of the active supervision app.
+ */
+ private void setSupervisionEnabledForUserInternal(
+ @UserIdInt int userId, boolean enabled, @Nullable String supervisionAppPackage) {
synchronized (getLockObject()) {
- getUserDataLocked(userId).supervisionEnabled = enabled;
+ SupervisionUserData data = getUserDataLocked(userId);
+ data.supervisionEnabled = enabled;
+ data.supervisionAppPackage = enabled ? supervisionAppPackage : null;
}
}
- /** Ensures that supervision is enabled when supervision app is the profile owner. */
+ /** Ensures that supervision is enabled when the supervision app is the profile owner. */
private void syncStateWithDevicePolicyManager(@UserIdInt int userId) {
- if (isProfileOwner(userId)) {
- setSupervisionEnabledForUser(userId, true);
+ final DevicePolicyManagerInternal dpmInternal = mInjector.getDpmInternal();
+ final ComponentName po =
+ dpmInternal != null ? dpmInternal.getProfileOwnerAsUser(userId) : null;
+
+ if (po != null && po.getPackageName().equals(getSystemSupervisionPackage())) {
+ setSupervisionEnabledForUserInternal(userId, true, po.getPackageName());
+ } else if (po != null && po.equals(getSupervisionProfileOwnerComponent())) {
+ // TODO(b/392071637): Consider not enabling supervision in case profile owner is given
+ // to the legacy supervision profile owner component.
+ setSupervisionEnabledForUserInternal(userId, true, po.getPackageName());
} else {
// TODO(b/381428475): Avoid disabling supervision when the app is not the profile owner.
// This might only be possible after introducing specific and public APIs to enable
- // supervision.
- setSupervisionEnabledForUser(userId, false);
+ // and disable supervision.
+ setSupervisionEnabledForUserInternal(userId, false, /* supervisionAppPackage= */ null);
}
}
- /** Returns whether the supervision app has profile owner status. */
- private boolean isProfileOwner(@UserIdInt int userId) {
- ComponentName profileOwner =
- mDpmInternal != null ? mDpmInternal.getProfileOwnerAsUser(userId) : null;
- return profileOwner != null && isSupervisionAppPackage(profileOwner.getPackageName());
+ /**
+ * Returns the {@link ComponentName} of the supervision profile owner component.
+ *
+ * <p>This component is used to give GMS Kids Module permission to supervise the device and may
+ * still be active during the transition to the {@code SYSTEM_SUPERVISION} role.
+ */
+ private ComponentName getSupervisionProfileOwnerComponent() {
+ return ComponentName.unflattenFromString(
+ mContext.getResources()
+ .getString(R.string.config_defaultSupervisionProfileOwnerComponent));
}
- /** Returns whether the given package name belongs to the supervision role holder. */
- private boolean isSupervisionAppPackage(String packageName) {
- return packageName.equals(
- mContext.getResources().getString(R.string.config_systemSupervision));
+ /** Returns the package assigned to the {@code SYSTEM_SUPERVISION} role. */
+ private String getSystemSupervisionPackage() {
+ return mContext.getResources().getString(R.string.config_systemSupervision);
}
/** Enforces that the caller has the given permission. */
@@ -177,6 +220,41 @@ public class SupervisionService extends ISupervisionManager.Stub {
mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED);
}
+ /** Provides local services in a lazy manner. */
+ static class Injector {
+ private final Context mContext;
+ private DevicePolicyManagerInternal mDpmInternal;
+ private PackageManager mPackageManager;
+ private UserManagerInternal mUserManagerInternal;
+
+ Injector(Context context) {
+ mContext = context;
+ }
+
+ @Nullable
+ DevicePolicyManagerInternal getDpmInternal() {
+ if (mDpmInternal == null) {
+ mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
+ }
+ return mDpmInternal;
+ }
+
+ PackageManager getPackageManager() {
+ if (mPackageManager == null) {
+ mPackageManager = mContext.getPackageManager();
+ }
+ return mPackageManager;
+ }
+
+ UserManagerInternal getUserManagerInternal() {
+ if (mUserManagerInternal == null) {
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+ }
+ return mUserManagerInternal;
+ }
+ }
+
+ /** Publishes local and binder services and allows the service to act during initialization. */
public static class Lifecycle extends SystemService {
private final SupervisionService mSupervisionService;
@@ -201,6 +279,7 @@ public class SupervisionService extends ISupervisionManager.Stub {
}
@VisibleForTesting
+ @SuppressLint("MissingPermission") // not needed for a service
void registerProfileOwnerListener() {
IntentFilter poIntentFilter = new IntentFilter();
poIntentFilter.addAction(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED);
@@ -209,7 +288,7 @@ public class SupervisionService extends ISupervisionManager.Stub {
.registerReceiverForAllUsers(
new ProfileOwnerBroadcastReceiver(),
poIntentFilter,
- /* brodcastPermission= */ null,
+ /* broadcastPermission= */ null,
/* scheduler= */ null);
}
@@ -228,19 +307,22 @@ public class SupervisionService extends ISupervisionManager.Stub {
}
}
- final SupervisionManagerInternal mInternal = new SupervisionManagerInternalImpl();
-
+ /** Implementation of the local service, API used by other services. */
private final class SupervisionManagerInternalImpl extends SupervisionManagerInternal {
@Override
public boolean isActiveSupervisionApp(int uid) {
- String[] packages = mPackageManager.getPackagesForUid(uid);
- if (packages == null) {
+ int userId = UserHandle.getUserId(uid);
+ String supervisionAppPackage = getActiveSupervisionAppPackage(userId);
+ if (supervisionAppPackage == null) {
return false;
}
- for (var packageName : packages) {
- if (SupervisionService.this.isSupervisionAppPackage(packageName)) {
- int userId = UserHandle.getUserId(uid);
- return SupervisionService.this.isSupervisionEnabledForUser(userId);
+
+ String[] packages = mInjector.getPackageManager().getPackagesForUid(uid);
+ if (packages != null) {
+ for (var packageName : packages) {
+ if (supervisionAppPackage.equals(packageName)) {
+ return true;
+ }
}
}
return false;
@@ -274,6 +356,7 @@ public class SupervisionService extends ISupervisionManager.Stub {
}
}
+ /** Deletes user data when the user gets removed. */
private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener {
@Override
public void onUserRemoved(UserInfo user) {
diff --git a/services/supervision/java/com/android/server/supervision/SupervisionServiceShellCommand.java b/services/supervision/java/com/android/server/supervision/SupervisionServiceShellCommand.java
index 2adaae3943f1..976642bd563d 100644
--- a/services/supervision/java/com/android/server/supervision/SupervisionServiceShellCommand.java
+++ b/services/supervision/java/com/android/server/supervision/SupervisionServiceShellCommand.java
@@ -32,16 +32,18 @@ public class SupervisionServiceShellCommand extends ShellCommand {
return handleDefaultCommands(null);
}
switch (cmd) {
- case "enable": return setEnabled(true);
- case "disable": return setEnabled(false);
- default: return handleDefaultCommands(cmd);
+ case "enable":
+ return setEnabled(true);
+ case "disable":
+ return setEnabled(false);
+ default:
+ return handleDefaultCommands(cmd);
}
}
private int setEnabled(boolean enabled) {
- final var pw = getOutPrintWriter();
final var userId = UserHandle.parseUserArg(getNextArgRequired());
- mService.setSupervisionEnabledForUser(userId, enabled);
+ mService.mInternal.setSupervisionEnabledForUser(userId, enabled);
return 0;
}
diff --git a/services/supervision/java/com/android/server/supervision/SupervisionUserData.java b/services/supervision/java/com/android/server/supervision/SupervisionUserData.java
index 1dd48f581bf4..06acb91509a1 100644
--- a/services/supervision/java/com/android/server/supervision/SupervisionUserData.java
+++ b/services/supervision/java/com/android/server/supervision/SupervisionUserData.java
@@ -26,6 +26,7 @@ import android.util.IndentingPrintWriter;
public class SupervisionUserData {
public final @UserIdInt int userId;
public boolean supervisionEnabled;
+ @Nullable public String supervisionAppPackage;
public boolean supervisionLockScreenEnabled;
@Nullable public PersistableBundle supervisionLockScreenOptions;
@@ -38,6 +39,7 @@ public class SupervisionUserData {
pw.println("User " + userId + ":");
pw.increaseIndent();
pw.println("supervisionEnabled: " + supervisionEnabled);
+ pw.println("supervisionAppPackage: " + supervisionAppPackage);
pw.println("supervisionLockScreenEnabled: " + supervisionLockScreenEnabled);
pw.println("supervisionLockScreenOptions: " + supervisionLockScreenOptions);
pw.decreaseIndent();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt
index 01061f16c279..0466e7572c2e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt
@@ -29,6 +29,7 @@ import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
private val TEST_PLUGIN_TYPE = PluginType(Int::class.java, "test_type")
+private val DISPLAY_ID = "display_id"
@SmallTest
class PluginManagerTest {
@@ -62,18 +63,18 @@ class PluginManagerTest {
fun testSubscribe() {
val pluginManager = createPluginManager()
- pluginManager.subscribe(TEST_PLUGIN_TYPE, mockListener)
+ pluginManager.subscribe(TEST_PLUGIN_TYPE, DISPLAY_ID, mockListener)
- verify(testInjector.mockStorage).addListener(TEST_PLUGIN_TYPE, mockListener)
+ verify(testInjector.mockStorage).addListener(TEST_PLUGIN_TYPE, DISPLAY_ID, mockListener)
}
@Test
fun testUnsubscribe() {
val pluginManager = createPluginManager()
- pluginManager.unsubscribe(TEST_PLUGIN_TYPE, mockListener)
+ pluginManager.unsubscribe(TEST_PLUGIN_TYPE, DISPLAY_ID, mockListener)
- verify(testInjector.mockStorage).removeListener(TEST_PLUGIN_TYPE, mockListener)
+ verify(testInjector.mockStorage).removeListener(TEST_PLUGIN_TYPE, DISPLAY_ID, mockListener)
}
private fun createPluginManager(enabled: Boolean = true): PluginManager {
@@ -86,11 +87,15 @@ class PluginManagerTest {
val mockPlugin1 = mock<Plugin>()
val mockPlugin2 = mock<Plugin>()
- override fun getPluginStorage(): PluginStorage {
+ override fun getPluginStorage(enabledTypes: Set<PluginType<*>>): PluginStorage {
return mockStorage
}
- override fun loadPlugins(context: Context?, storage: PluginStorage?): List<Plugin> {
+ override fun loadPlugins(
+ context: Context?,
+ storage: PluginStorage?,
+ enabledTypes: Set<PluginType<*>>
+ ): List<Plugin> {
return listOf(mockPlugin1, mockPlugin2)
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt
index 218e34134e93..2b06126588d6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt
@@ -23,19 +23,21 @@ import org.junit.Test
private val TEST_PLUGIN_TYPE1 = PluginType(String::class.java, "test_type1")
private val TEST_PLUGIN_TYPE2 = PluginType(String::class.java, "test_type2")
+private val DISPLAY_ID_1 = "display_1"
+private val DISPLAY_ID_2 = "display_2"
@SmallTest
class PluginStorageTest {
- val storage = PluginStorage()
+ var storage = PluginStorage(setOf(TEST_PLUGIN_TYPE1, TEST_PLUGIN_TYPE2))
@Test
fun testUpdateValue() {
val type1Value = "value1"
val testChangeListener = TestPluginChangeListener<String>()
- storage.addListener(TEST_PLUGIN_TYPE1, testChangeListener)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener)
- storage.updateValue(TEST_PLUGIN_TYPE1, type1Value)
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
assertThat(testChangeListener.receivedValue).isEqualTo(type1Value)
}
@@ -44,9 +46,9 @@ class PluginStorageTest {
fun testAddListener() {
val type1Value = "value1"
val testChangeListener = TestPluginChangeListener<String>()
- storage.updateValue(TEST_PLUGIN_TYPE1, type1Value)
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
- storage.addListener(TEST_PLUGIN_TYPE1, testChangeListener)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener)
assertThat(testChangeListener.receivedValue).isEqualTo(type1Value)
}
@@ -55,10 +57,10 @@ class PluginStorageTest {
fun testRemoveListener() {
val type1Value = "value1"
val testChangeListener = TestPluginChangeListener<String>()
- storage.addListener(TEST_PLUGIN_TYPE1, testChangeListener)
- storage.removeListener(TEST_PLUGIN_TYPE1, testChangeListener)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener)
+ storage.removeListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener)
- storage.updateValue(TEST_PLUGIN_TYPE1, type1Value)
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
assertThat(testChangeListener.receivedValue).isNull()
}
@@ -68,10 +70,10 @@ class PluginStorageTest {
val type1Value = "value1"
val type2Value = "value2"
val testChangeListener = TestPluginChangeListener<String>()
- storage.updateValue(TEST_PLUGIN_TYPE1, type1Value)
- storage.updateValue(TEST_PLUGIN_TYPE2, type2Value)
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
+ storage.updateValue(TEST_PLUGIN_TYPE2, DISPLAY_ID_1, type2Value)
- storage.addListener(TEST_PLUGIN_TYPE1, testChangeListener)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener)
assertThat(testChangeListener.receivedValue).isEqualTo(type1Value)
}
@@ -81,15 +83,74 @@ class PluginStorageTest {
val type1Value = "value1"
val testChangeListener1 = TestPluginChangeListener<String>()
val testChangeListener2 = TestPluginChangeListener<String>()
- storage.addListener(TEST_PLUGIN_TYPE1, testChangeListener1)
- storage.addListener(TEST_PLUGIN_TYPE2, testChangeListener2)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener1)
+ storage.addListener(TEST_PLUGIN_TYPE2, DISPLAY_ID_1, testChangeListener2)
- storage.updateValue(TEST_PLUGIN_TYPE1, type1Value)
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
assertThat(testChangeListener1.receivedValue).isEqualTo(type1Value)
assertThat(testChangeListener2.receivedValue).isNull()
}
+ @Test
+ fun testDisabledPluginType() {
+ storage = PluginStorage(setOf(TEST_PLUGIN_TYPE2))
+ val type1Value = "value1"
+ val testChangeListener = TestPluginChangeListener<String>()
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
+
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener)
+
+ assertThat(testChangeListener.receivedValue).isNull()
+ }
+
+ @Test
+ fun testUpdateGlobal_noDisplaySpecificValue() {
+ val type1Value = "value1"
+ val testChangeListener1 = TestPluginChangeListener<String>()
+ val testChangeListener2 = TestPluginChangeListener<String>()
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener1)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_2, testChangeListener2)
+
+ storage.updateGlobalValue(TEST_PLUGIN_TYPE1, type1Value)
+
+ assertThat(testChangeListener1.receivedValue).isEqualTo(type1Value)
+ assertThat(testChangeListener2.receivedValue).isEqualTo(type1Value)
+ }
+
+ @Test
+ fun testUpdateGlobal_withDisplaySpecificValue() {
+ val type1Value = "value1"
+ val type1GlobalValue = "value1Global"
+ val testChangeListener1 = TestPluginChangeListener<String>()
+ val testChangeListener2 = TestPluginChangeListener<String>()
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener1)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_2, testChangeListener2)
+
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
+ storage.updateGlobalValue(TEST_PLUGIN_TYPE1, type1GlobalValue)
+
+ assertThat(testChangeListener1.receivedValue).isEqualTo(type1Value)
+ assertThat(testChangeListener2.receivedValue).isEqualTo(type1GlobalValue)
+ }
+
+ @Test
+ fun testUpdateGlobal_withDisplaySpecificValueRemoved() {
+ val type1Value = "value1"
+ val type1GlobalValue = "value1Global"
+ val testChangeListener1 = TestPluginChangeListener<String>()
+ val testChangeListener2 = TestPluginChangeListener<String>()
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener1)
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_2, testChangeListener2)
+
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
+ storage.updateGlobalValue(TEST_PLUGIN_TYPE1, type1GlobalValue)
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, null)
+
+ assertThat(testChangeListener1.receivedValue).isEqualTo(type1GlobalValue)
+ assertThat(testChangeListener2.receivedValue).isEqualTo(type1GlobalValue)
+ }
+
private class TestPluginChangeListener<T> : PluginChangeListener<T> {
var receivedValue: T? = null
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index fe7cc923d3d1..1ef758cf192e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -3395,6 +3395,51 @@ public class MockingOomAdjusterTests {
}
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_BindUiServiceFromClientService() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ ServiceRecord s = makeServiceRecord(client);
+ mProcessStateController.setStartRequested(s, true);
+ mProcessStateController.setServiceLastActivityTime(s, SystemClock.uptimeMillis());
+ bindService(app, client, null, null, 0, mock(IBinder.class));
+
+ setWakefulness(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ updateOomAdj(app, client);
+ if (Flags.raiseBoundUiServiceThreshold()) {
+ assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
+ "service");
+ } else {
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND,
+ "cch-bound-ui-services");
+ }
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_BindUiServiceFromClientHome() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+
+ WindowProcessController wpc = client.getWindowProcessController();
+ doReturn(true).when(wpc).isHomeProcess();
+ bindService(app, client, null, null, 0, mock(IBinder.class));
+ setWakefulness(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ updateOomAdj(app, client);
+
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_HOME, expectedAdj, SCHED_GROUP_BACKGROUND,
+ "cch-bound-ui-services");
+ }
+
private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
String packageName, boolean hasShownUi) {
return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi(
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
index 89b48bad2358..d6349fc0651f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
@@ -16,6 +16,9 @@
package com.android.server.am;
+import static android.os.PowerWhitelistManager.REASON_NOTIFICATION_SERVICE;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
import static android.os.Process.INVALID_UID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -27,9 +30,12 @@ import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_OWNER_CANC
import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_OWNER_FORCE_STOPPED;
import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_SUPERSEDED;
import static com.android.server.am.PendingIntentRecord.CANCEL_REASON_USER_STOPPED;
+import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
import static com.android.server.am.PendingIntentRecord.cancelReasonToString;
+import static com.android.window.flags.Flags.balClearAllowlistDuration;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -39,9 +45,11 @@ import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
+import android.app.BackgroundStartPrivileges;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.IPackageManager;
+import android.os.Binder;
import android.os.Looper;
import android.os.UserHandle;
@@ -179,6 +187,41 @@ public class PendingIntentControllerTest {
}
}
+ @Test
+ public void testClearAllowBgActivityStartsClearsToken() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ Binder token = new Binder();
+ pir.setAllowBgActivityStarts(token, FLAG_ACTIVITY_SENDER);
+ assertEquals(BackgroundStartPrivileges.allowBackgroundActivityStarts(token),
+ pir.getBackgroundStartPrivilegesForActivitySender(token));
+ pir.clearAllowBgActivityStarts(token);
+ assertEquals(BackgroundStartPrivileges.NONE,
+ pir.getBackgroundStartPrivilegesForActivitySender(token));
+ }
+
+ @Test
+ public void testClearAllowBgActivityStartsClearsDuration() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ Binder token = new Binder();
+ pir.setAllowlistDurationLocked(token, 1000,
+ TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, REASON_NOTIFICATION_SERVICE,
+ "NotificationManagerService");
+ PendingIntentRecord.TempAllowListDuration allowlistDurationLocked =
+ pir.getAllowlistDurationLocked(token);
+ assertEquals(1000, allowlistDurationLocked.duration);
+ assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ allowlistDurationLocked.type);
+ pir.clearAllowBgActivityStarts(token);
+ PendingIntentRecord.TempAllowListDuration allowlistDurationLockedAfterClear =
+ pir.getAllowlistDurationLocked(token);
+ assertNotNull(allowlistDurationLockedAfterClear);
+ assertEquals(1000, allowlistDurationLockedAfterClear.duration);
+ assertEquals(balClearAllowlistDuration()
+ ? TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED
+ : TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ allowlistDurationLocked.type);
+ }
+
private void assertCancelReason(int expectedReason, int actualReason) {
final String errMsg = "Expected: " + cancelReasonToString(expectedReason)
+ "; Actual: " + cancelReasonToString(actualReason);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
index d427c9d9ee37..e94ef5bb4871 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
@@ -39,6 +39,8 @@ import android.os.Handler;
import android.os.Parcel;
import android.os.Process;
import android.os.UidBatteryConsumer;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.ravenwood.RavenwoodRule;
import android.util.SparseLongArray;
@@ -49,6 +51,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerProfile;
+import com.android.server.power.optimization.Flags;
import com.android.server.power.stats.processor.MultiStatePowerAttributor;
import org.junit.Before;
@@ -59,6 +62,7 @@ import org.junit.runner.RunWith;
import java.io.File;
import java.io.IOException;
import java.util.List;
+import java.util.concurrent.TimeUnit;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -68,11 +72,14 @@ public class BatteryUsageStatsProviderTest {
.setProvideMainThread(true)
.build();
+ @Rule(order = 1)
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
private static final long MINUTE_IN_MS = 60 * 1000;
private static final double PRECISION = 0.00001;
- @Rule(order = 1)
+ @Rule(order = 2)
public final BatteryUsageStatsRule mStatsRule =
new BatteryUsageStatsRule(12345)
.createTempDirectory()
@@ -868,4 +875,62 @@ public class BatteryUsageStatsProviderTest {
stats.close();
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_EXTENDED_BATTERY_HISTORY_CONTINUOUS_COLLECTION_ENABLED)
+ public void testIncludeSubsetOfHistory() throws IOException {
+ MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+ batteryStats.getHistory().setMaxHistoryBufferSize(100);
+ synchronized (batteryStats) {
+ batteryStats.setRecordAllHistoryLocked(true);
+ }
+ batteryStats.forceRecordAllHistory();
+ batteryStats.setNoAutoReset(true);
+
+ long lastIncludedEventTimestamp = 0;
+ String tag = "work work work work work work work work work work work work work work work";
+ for (int i = 1; i < 50; i++) {
+ mStatsRule.advanceTime(TimeUnit.MINUTES.toMillis(9));
+ synchronized (batteryStats) {
+ batteryStats.noteJobStartLocked(tag, 42);
+ }
+ mStatsRule.advanceTime(TimeUnit.MINUTES.toMillis(1));
+ synchronized (batteryStats) {
+ batteryStats.noteJobFinishLocked(tag, 42, 0);
+ }
+ lastIncludedEventTimestamp = mMonotonicClock.monotonicTime();
+ }
+
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), 0, mMockClock,
+ mMonotonicClock);
+
+ BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
+ .includeBatteryHistory()
+ .setPreferredHistoryDurationMs(TimeUnit.MINUTES.toMillis(20))
+ .build();
+ final BatteryUsageStats stats = provider.getBatteryUsageStats(batteryStats, query);
+ Parcel parcel = Parcel.obtain();
+ stats.writeToParcel(parcel, 0);
+ stats.close();
+
+ parcel.setDataPosition(0);
+ BatteryUsageStats actual = BatteryUsageStats.CREATOR.createFromParcel(parcel);
+
+ long firstIncludedEventTimestamp = 0;
+ try (BatteryStatsHistoryIterator it = actual.iterateBatteryStatsHistory()) {
+ BatteryStats.HistoryItem item;
+ while ((item = it.next()) != null) {
+ if (item.eventCode == BatteryStats.HistoryItem.EVENT_JOB_START) {
+ firstIncludedEventTimestamp = item.time;
+ break;
+ }
+ }
+ }
+ actual.close();
+
+ assertThat(firstIncludedEventTimestamp)
+ .isAtLeast(lastIncludedEventTimestamp - TimeUnit.MINUTES.toMillis(30));
+ }
}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 9b7bbe04132c..834fea46e505 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -113,7 +113,6 @@
<uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
- <uses-permission android:name="android.permission.CREATE_VIRTUAL_DEVICE" />
<uses-permission android:name="android.permission.MANAGE_KEY_GESTURES" />
<queries>
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 4ef602f1a64c..3511ae12497a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -58,9 +58,9 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.test.TestLooper;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.testing.DexmakerShareClassLoaderRule;
@@ -173,6 +173,8 @@ public class MagnificationControllerTest {
@Mock
private Scroller mMockScroller;
+ private TestLooper mTestLooper;
+
// To mock package-private class
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -199,14 +201,16 @@ public class MagnificationControllerTest {
mMockResolver = new MockContentResolver();
mMockResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- Looper looper = InstrumentationRegistry.getContext().getMainLooper();
- // Pretending ID of the Thread associated with looper as main thread ID in controller
- when(mContext.getMainLooper()).thenReturn(looper);
+ mTestLooper = new TestLooper();
+ when(mContext.getMainLooper()).thenReturn(
+ InstrumentationRegistry.getContext().getMainLooper());
when(mContext.getContentResolver()).thenReturn(mMockResolver);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
Settings.Secure.putFloatForUser(mMockResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, DEFAULT_SCALE,
CURRENT_USER_ID);
+ Settings.Secure.putFloatForUser(mMockResolver, Settings.Secure.KEY_REPEAT_ENABLED, 1,
+ CURRENT_USER_ID);
mScaleProvider = spy(new MagnificationScaleProvider(mContext));
when(mControllerCtx.getContext()).thenReturn(mContext);
@@ -251,7 +255,7 @@ public class MagnificationControllerTest {
mMagnificationController = spy(new MagnificationController(mService, globalLock, mContext,
mScreenMagnificationController, mMagnificationConnectionManager, mScaleProvider,
- ConcurrentUtils.DIRECT_EXECUTOR));
+ ConcurrentUtils.DIRECT_EXECUTOR, mTestLooper.getLooper()));
mMagnificationController.setMagnificationCapabilities(
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
@@ -261,6 +265,7 @@ public class MagnificationControllerTest {
@After
public void tearDown() {
+ mTestLooper.dispatchAll();
FakeSettingsProvider.clearSettingsProvider();
}
@@ -880,6 +885,69 @@ public class MagnificationControllerTest {
}
@Test
+ public void magnificationCallbacks_panMagnificationContinuous() throws RemoteException {
+ setMagnificationEnabled(MODE_FULLSCREEN);
+ mMagnificationController.onPerformScaleAction(TEST_DISPLAY, 8.0f, false);
+ reset(mScreenMagnificationController);
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ mDisplay.getMetrics(metrics);
+ float expectedStep = 27 * metrics.density;
+
+ float currentCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
+ float currentCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
+
+ // Start moving right using keyboard callbacks.
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_RIGHT);
+
+ float newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
+ float newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
+ expect.that(currentCenterX).isLessThan(newCenterX);
+ expect.that(newCenterX - currentCenterX).isWithin(0.01f).of(expectedStep);
+ expect.that(currentCenterY).isEqualTo(newCenterY);
+
+ currentCenterX = newCenterX;
+ currentCenterY = newCenterY;
+
+ // Wait for the initial delay to occur.
+ advanceTime(MagnificationController.INITIAL_KEYBOARD_REPEAT_INTERVAL_MS + 1);
+
+ // It should have moved again after the handler was triggered.
+ newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
+ newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
+ expect.that(currentCenterX).isLessThan(newCenterX);
+ expect.that(newCenterX - currentCenterX).isWithin(0.01f).of(expectedStep);
+ expect.that(currentCenterY).isEqualTo(newCenterY);
+ currentCenterX = newCenterX;
+ currentCenterY = newCenterY;
+
+ // Wait for repeat delay to occur.
+ advanceTime(MagnificationController.KEYBOARD_REPEAT_INTERVAL_MS + 1);
+
+ // It should have moved a third time.
+ newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
+ newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
+ expect.that(currentCenterX).isLessThan(newCenterX);
+ expect.that(newCenterX - currentCenterX).isWithin(0.01f).of(expectedStep);
+ expect.that(currentCenterY).isEqualTo(newCenterY);
+ currentCenterX = newCenterX;
+ currentCenterY = newCenterY;
+
+ // Stop magnification pan.
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_RIGHT);
+
+ // It should not move again, even after the appropriate delay.
+ advanceTime(MagnificationController.KEYBOARD_REPEAT_INTERVAL_MS + 1);
+
+ newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
+ newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
+ expect.that(newCenterX).isEqualTo(currentCenterX);
+ expect.that(newCenterY).isEqualTo(currentCenterY);
+ }
+
+ @Test
public void enableWindowMode_notifyMagnificationChanged() throws RemoteException {
setMagnificationEnabled(MODE_WINDOW);
@@ -1196,7 +1264,8 @@ public class MagnificationControllerTest {
assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, lastActivatedMode);
}
- @Test public void activateFullScreenMagnification_triggerCallback() throws RemoteException {
+ @Test
+ public void activateFullScreenMagnification_triggerCallback() throws RemoteException {
setMagnificationEnabled(MODE_FULLSCREEN);
verify(mMagnificationController).onFullScreenMagnificationActivationState(
eq(TEST_DISPLAY), eq(true));
@@ -1573,8 +1642,8 @@ public class MagnificationControllerTest {
float currentCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
float currentCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
- // Move right.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ // Move right using keyboard callbacks.
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_RIGHT);
float newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
float newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
@@ -1582,11 +1651,13 @@ public class MagnificationControllerTest {
expect.that(newCenterX - currentCenterX).isWithin(0.01f).of(expectedStep);
expect.that(currentCenterY).isEqualTo(newCenterY);
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_RIGHT);
currentCenterX = newCenterX;
currentCenterY = newCenterY;
// Move left.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_LEFT);
newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
@@ -1594,11 +1665,13 @@ public class MagnificationControllerTest {
expect.that(currentCenterX - newCenterX).isWithin(0.01f).of(expectedStep);
expect.that(currentCenterY).isEqualTo(newCenterY);
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_LEFT);
currentCenterX = newCenterX;
currentCenterY = newCenterY;
// Move down.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_DOWN);
newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
@@ -1606,17 +1679,22 @@ public class MagnificationControllerTest {
expect.that(currentCenterY).isLessThan(newCenterY);
expect.that(newCenterY - currentCenterY).isWithin(0.1f).of(expectedStep);
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_DOWN);
currentCenterX = newCenterX;
currentCenterY = newCenterY;
// Move up.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_UP);
newCenterX = mScreenMagnificationController.getCenterX(TEST_DISPLAY);
newCenterY = mScreenMagnificationController.getCenterY(TEST_DISPLAY);
expect.that(currentCenterX).isEqualTo(newCenterX);
expect.that(currentCenterY).isGreaterThan(newCenterY);
expect.that(currentCenterY - newCenterY).isWithin(0.01f).of(expectedStep);
+
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_UP);
}
private void testWindowMagnificationPanWithStepSize(float expectedStepDip)
@@ -1626,28 +1704,41 @@ public class MagnificationControllerTest {
final float expectedStep = expectedStepDip * metrics.density;
// Move right.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_RIGHT);
verify(mMockConnection.getConnection()).moveWindowMagnifier(eq(TEST_DISPLAY),
floatThat(step -> Math.abs(step - expectedStep) < 0.0001), eq(0.0f));
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_RIGHT);
// Move left.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_LEFT);
verify(mMockConnection.getConnection()).moveWindowMagnifier(eq(TEST_DISPLAY),
floatThat(step -> Math.abs(expectedStep - step) < 0.0001), eq(0.0f));
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_LEFT);
// Move down.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_DOWN);
verify(mMockConnection.getConnection()).moveWindowMagnifier(eq(TEST_DISPLAY),
eq(0.0f), floatThat(step -> Math.abs(expectedStep - step) < 0.0001));
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_DOWN);
// Move up.
- mMagnificationController.panMagnificationByStep(TEST_DISPLAY,
+ mMagnificationController.onPanMagnificationStart(TEST_DISPLAY,
MagnificationController.PAN_DIRECTION_UP);
verify(mMockConnection.getConnection()).moveWindowMagnifier(eq(TEST_DISPLAY),
eq(0.0f), floatThat(step -> Math.abs(expectedStep - step) < 0.0001));
+ mMagnificationController.onPanMagnificationStop(TEST_DISPLAY,
+ MagnificationController.PAN_DIRECTION_UP);
+ }
+
+ private void advanceTime(long timeMs) {
+ mTestLooper.moveTimeForward(timeMs);
+ mTestLooper.dispatchAll();
}
private static class WindowMagnificationMgrCallbackDelegate implements
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 605fed09dd9f..c7efa318af99 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -45,7 +45,6 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.biometrics.AuthenticationStateListener;
import android.hardware.biometrics.BiometricManager;
-import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceReceiver;
@@ -504,23 +503,9 @@ public class AuthServiceTest {
eq(callback));
}
- @Test(expected = UnsupportedOperationException.class)
- public void testGetLastAuthenticationTime_flaggedOff_throwsUnsupportedOperationException()
- throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
- setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
-
- mAuthService = new AuthService(mContext, mInjector);
- mAuthService.onStart();
-
- mAuthService.mImpl.getLastAuthenticationTime(0,
- BiometricManager.Authenticators.BIOMETRIC_STRONG);
- }
-
@Test
- public void testGetLastAuthenticationTime_flaggedOn_callsBiometricService()
+ public void testGetLastAuthenticationTime_callsBiometricService()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
mAuthService = new AuthService(mContext, mInjector);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index 8b9def98fbaf..d8a616214f96 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -18,9 +18,11 @@ package com.android.server.biometrics;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CONTENT_VIEW_MORE_OPTIONS_BUTTON;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON;
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED;
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED;
+import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS;
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGATIVE;
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_USER_CANCEL;
@@ -588,7 +590,7 @@ public class AuthSessionTest {
}
@Test
- public void testLogOnDialogDismissed_error() throws RemoteException {
+ public void testLogOnDialogDismissed_negativeButton() throws RemoteException {
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
@@ -615,6 +617,33 @@ public class AuthSessionTest {
}
@Test
+ public void testLogOnDialogDismissed_contentViewMoreOptionsButton() throws RemoteException {
+ final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
+
+ setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
+ final AuthSession session = createAuthSession(mSensors,
+ false /* checkDevicePolicyManager */,
+ Authenticators.BIOMETRIC_STRONG,
+ TEST_REQUEST_ID,
+ 0 /* operationId */,
+ 0 /* userId */);
+ session.goToInitialState();
+ assertEquals(STATE_AUTH_CALLED, session.getState());
+
+ session.onDialogDismissed(DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS, null);
+ verify(mBiometricFrameworkStatsLogger, times(1)).error(
+ (OperationContextExt) anyObject(),
+ eq(BiometricsProtoEnums.MODALITY_FACE),
+ eq(BiometricsProtoEnums.ACTION_AUTHENTICATE),
+ eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT),
+ eq(false),
+ anyLong(),
+ eq(BIOMETRIC_ERROR_CONTENT_VIEW_MORE_OPTIONS_BUTTON),
+ eq(0) /* vendorCode */,
+ eq(0) /* userId */);
+ }
+
+ @Test
public void onErrorReceivedAfterOnTryAgainPressedWhenSensorsAuthenticating() throws Exception {
setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index acca4cc294b3..9918a9a35c33 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -2014,20 +2014,9 @@ public class BiometricServiceTest {
verifyNoMoreInteractions(callback);
}
- @Test(expected = UnsupportedOperationException.class)
- public void testGetLastAuthenticationTime_flagOff_throwsUnsupportedOperationException()
- throws RemoteException {
- mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
-
- mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
- mBiometricService.mImpl.getLastAuthenticationTime(0, Authenticators.BIOMETRIC_STRONG);
- }
-
@Test
- public void testGetLastAuthenticationTime_flagOn_callsKeystoreAuthorization()
+ public void testGetLastAuthenticationTime_callsKeystoreAuthorization()
throws RemoteException {
- mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
-
final int[] hardwareAuthenticators = new int[] {
HardwareAuthenticatorType.PASSWORD,
HardwareAuthenticatorType.FINGERPRINT
diff --git a/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
index 57f3cc03980e..515d8e96d25c 100644
--- a/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/credentials/CredentialManagerServiceTest.java
@@ -51,20 +51,22 @@ public final class CredentialManagerServiceTest {
@Test
public void getStoredProviders_emptyValue_success() {
- Set<String> providers = CredentialManagerService.getStoredProviders("", "");
+ Set<String> providers = CredentialManagerService.getStoredProvidersExceptPackage(
+ "", "");
assertThat(providers.size()).isEqualTo(0);
}
@Test
public void getStoredProviders_nullValue_success() {
- Set<String> providers = CredentialManagerService.getStoredProviders(null, null);
+ Set<String> providers = CredentialManagerService.getStoredProvidersExceptPackage(
+ null, null);
assertThat(providers.size()).isEqualTo(0);
}
@Test
public void getStoredProviders_success() {
Set<String> providers =
- CredentialManagerService.getStoredProviders(
+ CredentialManagerService.getStoredProvidersExceptPackage(
"com.example.test/.TestActivity:com.example.test/.TestActivity2:"
+ "com.example.test2/.TestActivity:blank",
"com.example.test");
@@ -74,6 +76,7 @@ public final class CredentialManagerServiceTest {
@Test
public void onProviderRemoved_success() {
+ int userId = UserHandle.myUserId();
setSettingsKey(
Settings.Secure.AUTOFILL_SERVICE,
CredentialManagerService.AUTOFILL_PLACEHOLDER_VALUE);
@@ -85,7 +88,7 @@ public final class CredentialManagerServiceTest {
"com.example.test/com.example.test.TestActivity");
CredentialManagerService.updateProvidersWhenPackageRemoved(
- mSettingsWrapper, "com.example.test");
+ mSettingsWrapper, "com.example.test", userId);
assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE)).isEqualTo("");
assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE))
@@ -95,6 +98,7 @@ public final class CredentialManagerServiceTest {
@Test
public void onProviderRemoved_notPrimaryRemoved_success() {
+ int userId = UserHandle.myUserId();
final String testCredentialPrimaryValue = "com.example.test/com.example.test.TestActivity";
final String testCredentialValue =
"com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity";
@@ -106,7 +110,7 @@ public final class CredentialManagerServiceTest {
setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, testCredentialPrimaryValue);
CredentialManagerService.updateProvidersWhenPackageRemoved(
- mSettingsWrapper, "com.example.test3");
+ mSettingsWrapper, "com.example.test3", userId);
// Since the provider removed was not a primary provider then we should do nothing.
assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE))
@@ -120,6 +124,7 @@ public final class CredentialManagerServiceTest {
@Test
public void onProviderRemoved_isAlsoAutofillProvider_success() {
+ int userId = UserHandle.myUserId();
setSettingsKey(
Settings.Secure.AUTOFILL_SERVICE,
"com.example.test/com.example.test.AutofillProvider");
@@ -131,7 +136,7 @@ public final class CredentialManagerServiceTest {
"com.example.test/com.example.test.TestActivity");
CredentialManagerService.updateProvidersWhenPackageRemoved(
- mSettingsWrapper, "com.example.test");
+ mSettingsWrapper, "com.example.test", userId);
assertThat(getSettingsKey(Settings.Secure.AUTOFILL_SERVICE)).isEqualTo("");
assertThat(getSettingsKey(Settings.Secure.CREDENTIAL_SERVICE))
@@ -141,6 +146,7 @@ public final class CredentialManagerServiceTest {
@Test
public void onProviderRemoved_notPrimaryRemoved_isAlsoAutofillProvider_success() {
+ int userId = UserHandle.myUserId();
final String testCredentialPrimaryValue = "com.example.test/com.example.test.TestActivity";
final String testCredentialValue =
"com.example.test/com.example.test.TestActivity:com.example.test2/com.example.test2.TestActivity";
@@ -151,7 +157,7 @@ public final class CredentialManagerServiceTest {
setSettingsKey(Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, testCredentialPrimaryValue);
CredentialManagerService.updateProvidersWhenPackageRemoved(
- mSettingsWrapper, "com.example.test3");
+ mSettingsWrapper, "com.example.test3", userId);
// Since the provider removed was not a primary provider then we should do nothing.
assertCredentialPropertyEquals(
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index 3ced56a04138..a58a9cd2a28f 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -34,7 +34,6 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -53,15 +52,11 @@ import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
-import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions.LaunchCookie;
import android.app.AppOpsManager;
-import android.app.Instrumentation;
import android.app.KeyguardManager;
-import android.app.role.RoleManager;
-import android.companion.AssociationRequest;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -76,11 +71,9 @@ import android.media.projection.StopReason;
import android.os.Binder;
import android.os.IBinder;
import android.os.Looper;
-import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.test.TestLooper;
-import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
@@ -99,7 +92,6 @@ import com.android.server.testutils.OffsettableClock;
import com.android.server.wm.WindowManagerInternal;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -110,7 +102,6 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -292,8 +283,6 @@ public class MediaProjectionManagerServiceTest {
assertThat(stoppedCallback2).isFalse();
}
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
@Test
public void testCreateProjection_keyguardLocked() throws Exception {
MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
@@ -308,8 +297,6 @@ public class MediaProjectionManagerServiceTest {
assertThat(mIMediaProjectionCallback.mLatch.await(5, TimeUnit.SECONDS)).isTrue();
}
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
@Test
public void testCreateProjection_keyguardLocked_packageAllowlisted()
throws NameNotFoundException {
@@ -325,8 +312,6 @@ public class MediaProjectionManagerServiceTest {
assertThat(mService.getActiveProjectionInfo()).isNotNull();
}
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
@Test
public void testCreateProjection_keyguardLocked_AppOpMediaProjection()
throws NameNotFoundException {
@@ -347,50 +332,6 @@ public class MediaProjectionManagerServiceTest {
assertThat(mService.getActiveProjectionInfo()).isNotNull();
}
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
- @Test
- public void testCreateProjection_keyguardLocked_RoleHeld() {
- runWithRole(
- AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
- () -> {
- try {
- mAppInfo.privateFlags |= PRIVATE_FLAG_PRIVILEGED;
- doReturn(mAppInfo)
- .when(mPackageManager)
- .getApplicationInfoAsUser(
- anyString(),
- any(ApplicationInfoFlags.class),
- any(UserHandle.class));
- MediaProjectionManagerService.MediaProjection projection =
- mService.createProjectionInternal(
- Process.myUid(),
- mContext.getPackageName(),
- TYPE_MIRRORING,
- /* isPermanentGrant= */ false,
- UserHandle.CURRENT,
- DEFAULT_DISPLAY);
- doReturn(true).when(mKeyguardManager).isKeyguardLocked();
- doReturn(PackageManager.PERMISSION_DENIED)
- .when(mPackageManager)
- .checkPermission(RECORD_SENSITIVE_CONTENT, projection.packageName);
-
- projection.start(mIMediaProjectionCallback);
- projection.notifyVirtualDisplayCreated(10);
-
- // The projection was started because it was allowed to capture the
- // keyguard.
- assertWithMessage("Failed to run projection")
- .that(mService.getActiveProjectionInfo())
- .isNotNull();
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- });
- }
-
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
@Test
public void testCreateProjection_keyguardLocked_screenshareProtectionsDisabled()
throws NameNotFoundException {
@@ -416,8 +357,6 @@ public class MediaProjectionManagerServiceTest {
}
}
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
@Test
public void testCreateProjection_keyguardLocked_noDisplayCreated()
throws NameNotFoundException {
@@ -509,8 +448,6 @@ public class MediaProjectionManagerServiceTest {
assertThat(secondProjection).isNotEqualTo(projection);
}
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
@Test
public void testReuseProjection_keyguardNotLocked_startConsentDialog()
throws NameNotFoundException {
@@ -527,8 +464,6 @@ public class MediaProjectionManagerServiceTest {
verify(mContext).startActivityAsUser(any(), any());
}
- @EnableFlags(android.companion.virtualdevice.flags
- .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
@Test
public void testReuseProjection_keyguardLocked_noConsentDialog() throws NameNotFoundException {
MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
@@ -1302,48 +1237,6 @@ public class MediaProjectionManagerServiceTest {
return mService.getProjectionInternal(UID, PACKAGE_NAME);
}
- /**
- * Run the provided block giving the current context's package the provided role.
- */
- @SuppressWarnings("SameParameterValue")
- private void runWithRole(String role, Runnable block) {
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- String packageName = mContext.getPackageName();
- UserHandle user = instrumentation.getTargetContext().getUser();
- RoleManager roleManager = Objects.requireNonNull(
- mContext.getSystemService(RoleManager.class));
- try {
- CountDownLatch latch = new CountDownLatch(1);
- instrumentation.getUiAutomation().adoptShellPermissionIdentity(
- Manifest.permission.MANAGE_ROLE_HOLDERS,
- Manifest.permission.BYPASS_ROLE_QUALIFICATION);
-
- roleManager.setBypassingRoleQualification(true);
- roleManager.addRoleHolderAsUser(role, packageName,
- /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user,
- mContext.getMainExecutor(), success -> {
- if (success) {
- latch.countDown();
- } else {
- Assert.fail("Couldn't set role for test (failure) " + role);
- }
- });
- assertWithMessage("Couldn't set role for test (timeout) : " + role)
- .that(latch.await(1, TimeUnit.SECONDS)).isTrue();
- block.run();
-
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } finally {
- roleManager.removeRoleHolderAsUser(role, packageName,
- /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user,
- mContext.getMainExecutor(), (aBool) -> {});
- roleManager.setBypassingRoleQualification(false);
- instrumentation.getUiAutomation()
- .dropShellPermissionIdentity();
- }
- }
-
private static class FakeIMediaProjectionCallback extends IMediaProjectionCallback.Stub {
CountDownLatch mLatch = new CountDownLatch(1);
@Override
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java
index 379079a0018c..10ac0495d69a 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java
@@ -22,7 +22,6 @@ import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_
import static android.view.Display.INVALID_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -37,13 +36,10 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
-import android.app.Instrumentation;
import android.app.KeyguardManager;
-import android.app.role.RoleManager;
import android.companion.AssociationRequest;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -69,7 +65,6 @@ import com.android.server.SystemConfig;
import com.android.server.wm.WindowManagerInternal;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -79,9 +74,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import java.util.List;
import java.util.function.Consumer;
/**
@@ -123,6 +116,8 @@ public class MediaProjectionStopControllerTest {
private KeyguardManager mKeyguardManager;
@Mock
private TelecomManager mTelecomManager;
+ @Mock
+ private MediaProjectionStopController.RoleHolderProvider mRoleManager;
private AppOpsManager mAppOpsManager;
@Mock
@@ -145,7 +140,7 @@ public class MediaProjectionStopControllerTest {
mContext.addMockSystemService(TelecomManager.class, mTelecomManager);
mContext.setMockPackageManager(mPackageManager);
- mStopController = new MediaProjectionStopController(mContext, mStopConsumer);
+ mStopController = new MediaProjectionStopController(mContext, mStopConsumer, mRoleManager);
mService = new MediaProjectionManagerService(mContext,
mMediaProjectionMetricsLoggerInjector);
@@ -170,8 +165,6 @@ public class MediaProjectionStopControllerTest {
}
@Test
- @EnableFlags(
- android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
public void testMediaProjectionNotRestricted() throws Exception {
when(mKeyguardManager.isKeyguardLocked()).thenReturn(false);
@@ -180,8 +173,6 @@ public class MediaProjectionStopControllerTest {
}
@Test
- @EnableFlags(
- android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
public void testMediaProjectionRestricted() throws Exception {
MediaProjectionManagerService.MediaProjection mediaProjection = createMediaProjection();
mediaProjection.notifyVirtualDisplayCreated(1);
@@ -239,21 +230,13 @@ public class MediaProjectionStopControllerTest {
@Test
public void testExemptFromStoppingHasAppStreamingRole() throws Exception {
- runWithRole(
- AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
- () -> {
- try {
- MediaProjectionManagerService.MediaProjection mediaProjection =
- createMediaProjection();
- doReturn(PackageManager.PERMISSION_DENIED).when(
- mPackageManager).checkPermission(
- RECORD_SENSITIVE_CONTENT, mediaProjection.packageName);
- assertThat(mStopController.isExemptFromStopping(mediaProjection,
- MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- });
+ MediaProjectionManagerService.MediaProjection mediaProjection = createMediaProjection();
+ doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
+ RECORD_SENSITIVE_CONTENT, mediaProjection.packageName);
+ doReturn(List.of(mediaProjection.packageName)).when(mRoleManager).getRoleHoldersAsUser(
+ eq(AssociationRequest.DEVICE_PROFILE_APP_STREAMING), any(UserHandle.class));
+ assertThat(mStopController.isExemptFromStopping(mediaProjection,
+ MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue();
}
@Test
@@ -316,8 +299,6 @@ public class MediaProjectionStopControllerTest {
}
@Test
- @EnableFlags(
- android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
public void testKeyguardLockedStateChanged_unlocked() {
mStopController.onKeyguardLockedStateChanged(false);
@@ -325,8 +306,6 @@ public class MediaProjectionStopControllerTest {
}
@Test
- @EnableFlags(
- android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
public void testKeyguardLockedStateChanged_locked() {
mStopController.onKeyguardLockedStateChanged(true);
@@ -438,47 +417,4 @@ public class MediaProjectionStopControllerTest {
MediaProjectionManager.TYPE_SCREEN_CAPTURE, false, mContext.getUser(),
INVALID_DISPLAY);
}
-
- /**
- * Run the provided block giving the current context's package the provided role.
- */
- @SuppressWarnings("SameParameterValue")
- private void runWithRole(String role, Runnable block) {
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- String packageName = mContext.getPackageName();
- UserHandle user = instrumentation.getTargetContext().getUser();
- RoleManager roleManager = Objects.requireNonNull(
- mContext.getSystemService(RoleManager.class));
- try {
- CountDownLatch latch = new CountDownLatch(1);
- instrumentation.getUiAutomation().adoptShellPermissionIdentity(
- Manifest.permission.MANAGE_ROLE_HOLDERS,
- Manifest.permission.BYPASS_ROLE_QUALIFICATION);
-
- roleManager.setBypassingRoleQualification(true);
- roleManager.addRoleHolderAsUser(role, packageName,
- /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user,
- mContext.getMainExecutor(), success -> {
- if (success) {
- latch.countDown();
- } else {
- Assert.fail("Couldn't set role for test (failure) " + role);
- }
- });
- assertWithMessage("Couldn't set role for test (timeout) : " + role)
- .that(latch.await(1, TimeUnit.SECONDS)).isTrue();
- block.run();
-
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } finally {
- roleManager.removeRoleHolderAsUser(role, packageName,
- /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user,
- mContext.getMainExecutor(), (aBool) -> {
- });
- roleManager.setBypassingRoleQualification(false);
- instrumentation.getUiAutomation()
- .dropShellPermissionIdentity();
- }
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
index 5a89db143b34..4241aa95b09d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
@@ -109,7 +109,7 @@ public class ShortcutManagerTest7 extends BaseShortcutManagerTest {
assertEquals(3, mService.mMaxUpdatesPerInterval);
}
- public void testRestConfig() throws Exception {
+ public void disabled_testRestConfig() throws Exception {
mService.mMaxUpdatesPerInterval = 99;
mInjectedCallingUid = Process.SHELL_UID;
@@ -223,7 +223,7 @@ public class ShortcutManagerTest7 extends BaseShortcutManagerTest {
}
// This command is deprecated. Will remove the test later.
- public void testLauncherCommands() throws Exception {
+ public void disabled_testLauncherCommands() throws Exception {
prepareGetRoleHoldersAsUser(getSystemLauncher().activityInfo.packageName, USER_10);
prepareGetHomeActivitiesAsUser(
/* preferred */ getSystemLauncher().activityInfo.getComponentName(),
@@ -401,7 +401,7 @@ public class ShortcutManagerTest7 extends BaseShortcutManagerTest {
}
- public void testDumpsysArgs() {
+ public void disabled_testDumpsysArgs() {
checkDumpsysArgs(null, true, false, false);
checkDumpsysArgs(array("-u"), true, true, false);
checkDumpsysArgs(array("--uid"), true, true, false);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index 1c0ee09ccc6f..19c26f0b60ab 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -91,7 +91,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
assertEquals(USER_10, mService.getParentOrSelfUserId(USER_P0));
}
- public void testIsRequestPinShortcutSupported() {
+ public void disabled_testIsRequestPinShortcutSupported() {
setDefaultLauncher(USER_10, LAUNCHER_1);
setDefaultLauncher(USER_11, LAUNCHER_2);
@@ -168,7 +168,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut_notSupported() {
+ public void disabled_testRequestPinShortcut_notSupported() {
// User-0's launcher has no confirmation activity.
setDefaultLauncher(USER_10, LAUNCHER_1);
@@ -322,7 +322,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut() {
+ public void disabled_testRequestPinShortcut() {
checkRequestPinShortcut(/* resultIntent=*/ null);
}
@@ -332,7 +332,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
PendingIntent.FLAG_MUTABLE).getIntentSender();
}
- public void testRequestPinShortcut_withCallback() {
+ public void disabled_testRequestPinShortcut_withCallback() {
checkRequestPinShortcut(makeResultIntent());
}
@@ -410,7 +410,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut_noTargetActivity_noMainActivity() {
+ public void disabled_testRequestPinShortcut_noTargetActivity_noMainActivity() {
setDefaultLauncher(USER_10, LAUNCHER_1);
setDefaultLauncher(USER_11, LAUNCHER_2);
@@ -675,7 +675,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut_manifestExists_alreadyPinned() {
+ public void disabled_testRequestPinShortcut_manifestExists_alreadyPinned() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -757,7 +757,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut_wasDynamic_alreadyPinned() {
+ public void disabled_testRequestPinShortcut_wasDynamic_alreadyPinned() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -785,7 +785,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut_wasDynamic_disabled_alreadyPinned() {
+ public void disabled_testRequestPinShortcut_wasDynamic_disabled_alreadyPinned() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -816,7 +816,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut_wasManifest_alreadyPinned() {
+ public void disabled_testRequestPinShortcut_wasManifest_alreadyPinned() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -910,7 +910,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
});
}
- public void testRequestPinShortcut_manifestExists_alreadyPinnedByAnother() {
+ public void disabled_testRequestPinShortcut_manifestExists_alreadyPinnedByAnother() {
// Initially all launchers have the shortcut permission, until we call setDefaultLauncher().
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -1106,7 +1106,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
/**
* When trying to pin an existing shortcut, the new fields shouldn't override existing fields.
*/
- public void testRequestPinShortcut_manifestExists_titleWontChange() {
+ public void disabled_testRequestPinShortcut_manifestExists_titleWontChange() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -1287,7 +1287,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
* The manifest shortcut existed, but before accepting(), it's removed. Because the request
* has a partial shortcut, accept() should fail.
*/
- public void testRequestPinShortcut_manifestExists_thenRemoved_error() {
+ public void disabled_testRequestPinShortcut_manifestExists_thenRemoved_error() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -1344,7 +1344,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
* The manifest shortcut existed, but before accepting(), it's removed. Because the request
* has all the mandatory fields, we can go ahead and still publish it.
*/
- public void testRequestPinShortcut_manifestExists_thenRemoved_okay() {
+ public void disabled_testRequestPinShortcut_manifestExists_thenRemoved_okay() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -1478,7 +1478,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
* The manifest shortcut existed, but before accepting(), it's removed. Because the request
* has a partial shortcut, accept() should fail.
*/
- public void testRequestPinShortcut_manifestExists_thenDisabled_error() {
+ public void disabled_testRequestPinShortcut_manifestExists_thenDisabled_error() {
setDefaultLauncher(USER_10, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
index 5862ac65eba9..b150b1495042 100644
--- a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
+++ b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
@@ -92,6 +92,21 @@ class SupervisionServiceTest {
simulateUserStarting(USER_ID)
assertThat(service.isSupervisionEnabledForUser(USER_ID)).isTrue()
+ assertThat(service.getActiveSupervisionAppPackage(USER_ID))
+ .isEqualTo(systemSupervisionPackage)
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SYNC_WITH_DPM)
+ fun onUserStarting_legacyProfileOwnerComponent_enablesSupervision() {
+ whenever(mockDpmInternal.getProfileOwnerAsUser(USER_ID))
+ .thenReturn(supervisionProfileOwnerComponent)
+
+ simulateUserStarting(USER_ID)
+
+ assertThat(service.isSupervisionEnabledForUser(USER_ID)).isTrue()
+ assertThat(service.getActiveSupervisionAppPackage(USER_ID))
+ .isEqualTo(supervisionProfileOwnerComponent.packageName)
}
@Test
@@ -103,6 +118,7 @@ class SupervisionServiceTest {
simulateUserStarting(USER_ID, preCreated = true)
assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse()
+ assertThat(service.getActiveSupervisionAppPackage(USER_ID)).isNull()
}
@Test
@@ -114,6 +130,7 @@ class SupervisionServiceTest {
simulateUserStarting(USER_ID)
assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse()
+ assertThat(service.getActiveSupervisionAppPackage(USER_ID)).isNull()
}
@Test
@@ -125,6 +142,21 @@ class SupervisionServiceTest {
broadcastProfileOwnerChanged(USER_ID)
assertThat(service.isSupervisionEnabledForUser(USER_ID)).isTrue()
+ assertThat(service.getActiveSupervisionAppPackage(USER_ID))
+ .isEqualTo(systemSupervisionPackage)
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_SYNC_WITH_DPM)
+ fun profileOwnerChanged_legacyProfileOwnerComponent_enablesSupervision() {
+ whenever(mockDpmInternal.getProfileOwnerAsUser(USER_ID))
+ .thenReturn(supervisionProfileOwnerComponent)
+
+ broadcastProfileOwnerChanged(USER_ID)
+
+ assertThat(service.isSupervisionEnabledForUser(USER_ID)).isTrue()
+ assertThat(service.getActiveSupervisionAppPackage(USER_ID))
+ .isEqualTo(supervisionProfileOwnerComponent.packageName)
}
@Test
@@ -136,6 +168,7 @@ class SupervisionServiceTest {
broadcastProfileOwnerChanged(USER_ID)
assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse()
+ assertThat(service.getActiveSupervisionAppPackage(USER_ID)).isNull()
}
@Test
@@ -175,7 +208,7 @@ class SupervisionServiceTest {
}
@Test
- fun supervisionEnabledForUser_internal() {
+ fun setSupervisionEnabledForUser_internal() {
assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse()
service.mInternal.setSupervisionEnabledForUser(USER_ID, true)
@@ -205,6 +238,13 @@ class SupervisionServiceTest {
private val systemSupervisionPackage: String
get() = context.getResources().getString(R.string.config_systemSupervision)
+ private val supervisionProfileOwnerComponent: ComponentName
+ get() =
+ context
+ .getResources()
+ .getString(R.string.config_defaultSupervisionProfileOwnerComponent)
+ .let(ComponentName::unflattenFromString)!!
+
private fun simulateUserStarting(userId: Int, preCreated: Boolean = false) {
val userInfo = UserInfo(userId, /* name= */ "tempUser", /* flags= */ 0)
userInfo.preCreated = preCreated
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 842c441e09f2..857a9767d9ee 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -452,14 +452,14 @@ public class SystemConfigTest {
+ " <library \n"
+ " name=\"foo\"\n"
+ " file=\"" + mFooJar + "\"\n"
- + " on-bootclasspath-before=\"Q\"\n"
+ + " on-bootclasspath-before=\"A\"\n"
+ " on-bootclasspath-since=\"W\"\n"
+ " />\n\n"
+ " </permissions>";
parseSharedLibraries(contents);
assertFooIsOnlySharedLibrary();
SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
- assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
+ assertThat(entry.onBootclasspathBefore).isEqualTo("A");
assertThat(entry.onBootclasspathSince).isEqualTo("W");
}
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index a63a38da3740..0eb20eb22380 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -20,6 +20,7 @@ android_test {
],
static_libs: [
+ "compatibility-device-util-axt-minus-dexmaker",
"frameworks-base-testutils",
"services.accessibility",
"services.core",
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index 4315254f68a9..69f17757b367 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -45,6 +45,8 @@
<provider android:name=".DummyProvider"
android:authorities="com.android.services.uitests" />
+ <activity android:name="android.app.ExampleActivity" />
+
</application>
<instrumentation
diff --git a/services/tests/uiservicestests/src/android/app/ExampleActivity.java b/services/tests/uiservicestests/src/android/app/ExampleActivity.java
new file mode 100644
index 000000000000..58395e4d75e1
--- /dev/null
+++ b/services/tests/uiservicestests/src/android/app/ExampleActivity.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+public class ExampleActivity extends Activity {
+}
diff --git a/services/tests/uiservicestests/src/android/app/NotificationManagerZenTest.java b/services/tests/uiservicestests/src/android/app/NotificationManagerZenTest.java
new file mode 100644
index 000000000000..779fa1aa2f72
--- /dev/null
+++ b/services/tests/uiservicestests/src/android/app/NotificationManagerZenTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
+import static android.app.NotificationSystemUtil.runAsSystemUi;
+import static android.app.NotificationSystemUtil.toggleNotificationPolicyAccess;
+import static android.service.notification.Condition.STATE_FALSE;
+import static android.service.notification.Condition.STATE_TRUE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.service.notification.Condition;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+
+@RunWith(AndroidJUnit4.class)
+public class NotificationManagerZenTest {
+
+ private Context mContext;
+ private NotificationManager mNotificationManager;
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = ApplicationProvider.getApplicationContext();
+ mNotificationManager = mContext.getSystemService(NotificationManager.class);
+
+ toggleNotificationPolicyAccess(mContext, mContext.getPackageName(), true);
+ runAsSystemUi(() -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL));
+ removeAutomaticZenRules();
+ }
+
+ @After
+ public void tearDown() {
+ runAsSystemUi(() -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL));
+ removeAutomaticZenRules();
+ }
+
+ private void removeAutomaticZenRules() {
+ // Delete AZRs created by this test (query "as app", then delete "as system" so they are
+ // not preserved to be restored later).
+ Map<String, AutomaticZenRule> rules = mNotificationManager.getAutomaticZenRules();
+ runAsSystemUi(() -> {
+ for (String ruleId : rules.keySet()) {
+ mNotificationManager.removeAutomaticZenRule(ruleId);
+ }
+ });
+ }
+
+ @Test
+ @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void setAutomaticZenRuleState_manualActivation() {
+ AutomaticZenRule ruleToCreate = createZenRule("rule");
+ String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
+ Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on",
+ STATE_TRUE, Condition.SOURCE_USER_ACTION);
+ Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
+ STATE_FALSE, Condition.SOURCE_USER_ACTION);
+ Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
+ STATE_TRUE);
+ Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
+ STATE_FALSE);
+
+ // User manually activates -> it's active.
+ runAsSystemUi(
+ () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // User manually deactivates -> it's inactive.
+ runAsSystemUi(
+ () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // And app can activate and deactivate.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void setAutomaticZenRuleState_manualDeactivation() {
+ AutomaticZenRule ruleToCreate = createZenRule("rule");
+ String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
+ Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on",
+ STATE_TRUE, Condition.SOURCE_USER_ACTION);
+ Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
+ STATE_FALSE, Condition.SOURCE_USER_ACTION);
+ Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
+ STATE_TRUE);
+ Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
+ STATE_FALSE);
+
+ // App activates rule.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // User manually deactivates -> it's inactive.
+ runAsSystemUi(
+ () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // User manually reactivates -> it's active.
+ runAsSystemUi(
+ () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // That manual activation removed the override-deactivate, but didn't put an
+ // override-activate, so app can deactivate when its natural schedule ends.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void setAutomaticZenRuleState_respectsManuallyActivated() {
+ AutomaticZenRule ruleToCreate = createZenRule("rule");
+ String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
+ Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on",
+ STATE_TRUE, Condition.SOURCE_USER_ACTION);
+ Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
+ STATE_TRUE);
+ Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
+ STATE_FALSE);
+
+ // App thinks rule should be inactive.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // Manually activate -> it's active.
+ runAsSystemUi(() -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // App says it should be inactive, but it's ignored.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // App says it should be active. No change now...
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // ... but when the app wants to deactivate next time, it works.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void setAutomaticZenRuleState_respectsManuallyDeactivated() {
+ AutomaticZenRule ruleToCreate = createZenRule("rule");
+ String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
+ Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
+ STATE_FALSE, Condition.SOURCE_USER_ACTION);
+ Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
+ STATE_TRUE);
+ Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
+ STATE_FALSE);
+
+ // App activates rule.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // User manually deactivates -> it's inactive.
+ runAsSystemUi(
+ () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // App says it should be active, but it's ignored.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // App says it should be inactive. No change now...
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // ... but when the app wants to activate next time, it works.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void setAutomaticZenRuleState_manualActivationFromApp() {
+ AutomaticZenRule ruleToCreate = createZenRule("rule");
+ String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
+ Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
+ STATE_TRUE, Condition.SOURCE_USER_ACTION);
+ Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
+ STATE_FALSE, Condition.SOURCE_USER_ACTION);
+ Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
+ STATE_TRUE);
+ Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
+ STATE_FALSE);
+
+ // App activates rule.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // User manually deactivates from SysUI -> it's inactive.
+ runAsSystemUi(
+ () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // User manually activates from App -> it's active.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // And app can automatically deactivate it later.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+ }
+
+ @Test
+ @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
+ public void setAutomaticZenRuleState_manualDeactivationFromApp() {
+ AutomaticZenRule ruleToCreate = createZenRule("rule");
+ String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
+ Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
+ STATE_TRUE, Condition.SOURCE_USER_ACTION);
+ Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
+ STATE_FALSE, Condition.SOURCE_USER_ACTION);
+ Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
+ STATE_TRUE);
+
+ // User manually activates from SysUI -> it's active.
+ runAsSystemUi(
+ () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+
+ // User manually deactivates from App -> it's inactive.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
+
+ // And app can automatically activate it later.
+ mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
+ assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
+ }
+
+ private AutomaticZenRule createZenRule(String name) {
+ return createZenRule(name, NotificationManager.INTERRUPTION_FILTER_PRIORITY);
+ }
+
+ private AutomaticZenRule createZenRule(String name, int filter) {
+ return new AutomaticZenRule(name, null,
+ new ComponentName(mContext, ExampleActivity.class),
+ new Uri.Builder().scheme("scheme")
+ .appendPath("path")
+ .appendQueryParameter("fake_rule", "fake_value")
+ .build(), null, filter, true);
+ }
+}
diff --git a/services/tests/uiservicestests/src/android/app/NotificationSystemUtil.java b/services/tests/uiservicestests/src/android/app/NotificationSystemUtil.java
new file mode 100644
index 000000000000..cf6e39b962ab
--- /dev/null
+++ b/services/tests/uiservicestests/src/android/app/NotificationSystemUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static org.junit.Assert.assertEquals;
+
+import android.Manifest;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.AmUtils;
+import com.android.compatibility.common.util.FileUtils;
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.ThrowingRunnable;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class NotificationSystemUtil {
+
+ /**
+ * Runs a {@link ThrowingRunnable} as the Shell, while adopting SystemUI's permission (as
+ * checked by {@code NotificationManagerService#isCallerSystemOrSystemUi}).
+ */
+ protected static void runAsSystemUi(@NonNull ThrowingRunnable runnable) {
+ SystemUtil.runWithShellPermissionIdentity(
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ runnable, Manifest.permission.STATUS_BAR_SERVICE);
+ }
+
+ static void toggleNotificationPolicyAccess(Context context, String packageName,
+ boolean on) throws IOException {
+
+ String command = " cmd notification " + (on ? "allow_dnd " : "disallow_dnd ") + packageName
+ + " " + context.getUserId();
+
+ runCommand(command, InstrumentationRegistry.getInstrumentation());
+ AmUtils.waitForBroadcastBarrier();
+
+ NotificationManager nm = context.getSystemService(NotificationManager.class);
+ assertEquals("Notification Policy Access Grant is "
+ + nm.isNotificationPolicyAccessGranted() + " not " + on + " for "
+ + packageName, on, nm.isNotificationPolicyAccessGranted());
+ }
+
+ private static void runCommand(String command, Instrumentation instrumentation)
+ throws IOException {
+ UiAutomation uiAutomation = instrumentation.getUiAutomation();
+ try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(
+ uiAutomation.executeShellCommand(command))) {
+ FileUtils.readInputStreamFully(fis);
+ }
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index d1afa38cf3f6..839f27634d0f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -17,6 +17,7 @@ package com.android.server.notification;
import static android.os.UserHandle.USER_ALL;
import static android.service.notification.Adjustment.KEY_IMPORTANCE;
+import static android.service.notification.Adjustment.KEY_SUMMARIZATION;
import static android.service.notification.Adjustment.KEY_TYPE;
import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION;
import static android.service.notification.Adjustment.TYPE_NEWS;
@@ -45,6 +46,7 @@ import static org.mockito.Mockito.when;
import android.Manifest;
import android.app.ActivityManager;
+import android.app.Flags;
import android.app.INotificationManager;
import android.content.ComponentName;
import android.content.Context;
@@ -705,12 +707,12 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
@Test
@EnableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
public void testSetAssistantAdjustmentKeyTypeState_allow() {
- assertThat(mAssistants.getAllowedAdjustmentKeyTypes()).asList()
+ assertThat(mAssistants.getAllowedClassificationTypes()).asList()
.containsExactly(TYPE_PROMOTION);
mAssistants.setAssistantAdjustmentKeyTypeState(TYPE_CONTENT_RECOMMENDATION, true);
- assertThat(mAssistants.getAllowedAdjustmentKeyTypes()).asList()
+ assertThat(mAssistants.getAllowedClassificationTypes()).asList()
.containsExactlyElementsIn(List.of(TYPE_PROMOTION, TYPE_CONTENT_RECOMMENDATION));
}
@@ -718,7 +720,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
@EnableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION)
public void testSetAssistantAdjustmentKeyTypeState_disallow() {
mAssistants.setAssistantAdjustmentKeyTypeState(TYPE_PROMOTION, false);
- assertThat(mAssistants.getAllowedAdjustmentKeyTypes()).isEmpty();
+ assertThat(mAssistants.getAllowedClassificationTypes()).isEmpty();
}
@Test
@@ -731,7 +733,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
writeXmlAndReload(USER_ALL);
- assertThat(mAssistants.getAllowedAdjustmentKeyTypes()).asList()
+ assertThat(mAssistants.getAllowedClassificationTypes()).asList()
.containsExactlyElementsIn(List.of(TYPE_NEWS, TYPE_CONTENT_RECOMMENDATION));
}
@@ -742,105 +744,105 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
writeXmlAndReload(USER_ALL);
- assertThat(mAssistants.getAllowedAdjustmentKeyTypes()).asList()
+ assertThat(mAssistants.getAllowedClassificationTypes()).asList()
.containsExactly(TYPE_PROMOTION);
}
@Test
- @EnableFlags({android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION,
- android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
- public void testGetTypeAdjustmentDeniedPackages() throws Exception {
- String pkg = "my.package";
- String pkg2 = "my.package.2";
- assertThat(mAssistants.isTypeAdjustmentAllowedForPackage(pkg)).isTrue();
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).isEmpty();
-
- mAssistants.setTypeAdjustmentForPackageState(pkg, true);
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).isEmpty();
- mAssistants.setTypeAdjustmentForPackageState(pkg, false);
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).asList()
- .containsExactly(pkg);
- mAssistants.setTypeAdjustmentForPackageState(pkg2, true);
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).asList()
- .containsExactly(pkg);
- mAssistants.setTypeAdjustmentForPackageState(pkg2, false);
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).asList()
- .containsExactly(pkg, pkg2);
- }
-
- @Test
- @EnableFlags(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- public void testSetTypeAdjustmentForPackageState_allowsAndDenies() {
- // Given that a package is allowed to have its type adjusted,
+ @EnableFlags({Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI, Flags.FLAG_NM_SUMMARIZATION,
+ Flags.FLAG_NM_SUMMARIZATION_UI})
+ public void testSetAdjustmentSupportedForPackage_allowsAndDenies() {
+ // Given that a package is allowed to have summarization adjustments
+ String key = KEY_SUMMARIZATION;
String allowedPackage = "allowed.package";
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).isEmpty();
- mAssistants.setTypeAdjustmentForPackageState(allowedPackage, true);
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).isEmpty();
- assertTrue(mAssistants.isTypeAdjustmentAllowedForPackage(allowedPackage));
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, allowedPackage)).isTrue();
// Set type adjustment disallowed for this package
- mAssistants.setTypeAdjustmentForPackageState(allowedPackage, false);
+ mAssistants.setAdjustmentSupportedForPackage(key, allowedPackage, false);
// Then the package is marked as denied
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).asList()
- .containsExactly(allowedPackage);
- assertFalse(mAssistants.isTypeAdjustmentAllowedForPackage(allowedPackage));
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, allowedPackage)).isFalse();
// Set type adjustment allowed again
- mAssistants.setTypeAdjustmentForPackageState(allowedPackage, true);
+ mAssistants.setAdjustmentSupportedForPackage(key, allowedPackage, true);
// Then the package is marked as allowed again
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).isEmpty();
- assertTrue(mAssistants.isTypeAdjustmentAllowedForPackage(allowedPackage));
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, allowedPackage)).isTrue();
}
@Test
- @EnableFlags(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- public void testSetAssistantAdjustmentKeyTypeStateForPackage_deniesMultiple() {
- // Given packages not allowed to have their type adjusted,
+ @EnableFlags({Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI, Flags.FLAG_NM_SUMMARIZATION,
+ Flags.FLAG_NM_SUMMARIZATION_UI})
+ public void testSetAdjustmentSupportedForPackage_deniesMultiple() {
+ // Given packages not allowed to have summarizations applied
+ String key = KEY_SUMMARIZATION;
String deniedPkg1 = "denied.Pkg1";
String deniedPkg2 = "denied.Pkg2";
String deniedPkg3 = "denied.Pkg3";
// Set type adjustment disallowed for these packages
- mAssistants.setTypeAdjustmentForPackageState(deniedPkg1, false);
- mAssistants.setTypeAdjustmentForPackageState(deniedPkg2, false);
- mAssistants.setTypeAdjustmentForPackageState(deniedPkg3, false);
+ mAssistants.setAdjustmentSupportedForPackage(key, deniedPkg1, false);
+ mAssistants.setAdjustmentSupportedForPackage(key, deniedPkg2, false);
+ mAssistants.setAdjustmentSupportedForPackage(key, deniedPkg3, false);
// Then the packages are marked as denied
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).asList()
- .containsExactlyElementsIn(List.of(deniedPkg1, deniedPkg2, deniedPkg3));
- assertFalse(mAssistants.isTypeAdjustmentAllowedForPackage(deniedPkg1));
- assertFalse(mAssistants.isTypeAdjustmentAllowedForPackage(deniedPkg2));
- assertFalse(mAssistants.isTypeAdjustmentAllowedForPackage(deniedPkg3));
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg1)).isFalse();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg2)).isFalse();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg3)).isFalse();
// And when we re-allow one of them,
- mAssistants.setTypeAdjustmentForPackageState(deniedPkg2, true);
+ mAssistants.setAdjustmentSupportedForPackage(key, deniedPkg2, true);
// Then the rest of the original packages are still marked as denied.
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).asList()
- .containsExactlyElementsIn(List.of(deniedPkg1, deniedPkg3));
- assertFalse(mAssistants.isTypeAdjustmentAllowedForPackage(deniedPkg1));
- assertTrue(mAssistants.isTypeAdjustmentAllowedForPackage(deniedPkg2));
- assertFalse(mAssistants.isTypeAdjustmentAllowedForPackage(deniedPkg3));
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg1)).isFalse();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg2)).isTrue();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg3)).isFalse();
}
@Test
- @EnableFlags(android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI)
- public void testSetAssistantAdjustmentKeyTypeStateForPackage_readWriteXml() throws Exception {
+ @EnableFlags({Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI, Flags.FLAG_NM_SUMMARIZATION,
+ Flags.FLAG_NM_SUMMARIZATION_UI})
+ public void testSetAdjustmentSupportedForPackage_readWriteXml_singleAdjustment()
+ throws Exception {
mAssistants.loadDefaultsFromConfig(true);
+ String key = KEY_SUMMARIZATION;
String deniedPkg1 = "denied.Pkg1";
String allowedPkg2 = "allowed.Pkg2";
String deniedPkg3 = "denied.Pkg3";
- // Set type adjustment disallowed or allowed for these packages
- mAssistants.setTypeAdjustmentForPackageState(deniedPkg1, false);
- mAssistants.setTypeAdjustmentForPackageState(allowedPkg2, true);
- mAssistants.setTypeAdjustmentForPackageState(deniedPkg3, false);
+ // Set summarization adjustment disallowed or allowed for these packages
+ mAssistants.setAdjustmentSupportedForPackage(key, deniedPkg1, false);
+ mAssistants.setAdjustmentSupportedForPackage(key, allowedPkg2, true);
+ mAssistants.setAdjustmentSupportedForPackage(key, deniedPkg3, false);
+
+ writeXmlAndReload(USER_ALL);
+
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg1)).isFalse();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, allowedPkg2)).isTrue();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(key, deniedPkg3)).isFalse();
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI, Flags.FLAG_NM_SUMMARIZATION,
+ Flags.FLAG_NM_SUMMARIZATION_UI})
+ public void testSetAdjustmentSupportedForPackage_readWriteXml_multipleAdjustments()
+ throws Exception {
+ mAssistants.loadDefaultsFromConfig(true);
+ String deniedPkg1 = "denied.Pkg1";
+ String deniedPkg2 = "denied.Pkg2";
+ String deniedPkg3 = "denied.Pkg3";
+ // Set summarization adjustment disallowed these packages
+ mAssistants.setAdjustmentSupportedForPackage(KEY_SUMMARIZATION, deniedPkg1, false);
+ mAssistants.setAdjustmentSupportedForPackage(KEY_SUMMARIZATION, deniedPkg3, false);
+ // Set classification adjustment disallowed for these packages
+ mAssistants.setAdjustmentSupportedForPackage(KEY_TYPE, deniedPkg2, false);
writeXmlAndReload(USER_ALL);
- assertThat(mAssistants.getTypeAdjustmentDeniedPackages()).asList()
- .containsExactlyElementsIn(List.of(deniedPkg1, deniedPkg3));
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(KEY_SUMMARIZATION, deniedPkg1))
+ .isFalse();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(KEY_TYPE, deniedPkg2)).isFalse();
+ assertThat(mAssistants.isAdjustmentAllowedForPackage(KEY_SUMMARIZATION, deniedPkg3))
+ .isFalse();
}
@Test
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 a8fcadd9dd74..caff9139e26c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -24,6 +24,7 @@ import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_
import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.SHOW_IMMEDIATELY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.Flags.FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS;
+import static android.app.Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS;
import static android.app.Flags.FLAG_REDACT_SENSITIVE_CONTENT_NOTIFICATIONS_ON_LOCKSCREEN;
import static android.app.Flags.FLAG_SORT_SECTION_BY_TIME;
import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP;
@@ -604,7 +605,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
return FlagsParameterization.allCombinationsOf(
- FLAG_NOTIFICATION_CLASSIFICATION);
+ FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NM_BINDER_PERF_CACHE_CHANNELS);
}
public NotificationManagerServiceTest(FlagsParameterization flags) {
@@ -826,6 +827,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.setAttentionHelper(mAttentionHelper);
mService.setLockPatternUtils(mock(LockPatternUtils.class));
+ // make sure PreferencesHelper doesn't try to interact with any real caches
+ PreferencesHelper prefHelper = spy(mService.mPreferencesHelper);
+ doNothing().when(prefHelper).invalidateNotificationChannelCache();
+ mService.setPreferencesHelper(prefHelper);
+
// Return first true for RoleObserver main-thread check
when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
ModuleInfo moduleInfo = new ModuleInfo();
@@ -7677,7 +7683,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
// Set up notifications that will be adjusted
final NotificationRecord r1 = spy(generateNotificationRecord(
@@ -12007,7 +12013,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
@DisableFlags(android.app.Flags.FLAG_REMOVE_REMOTE_VIEWS)
public void testRemoveLargeRemoteViews() throws Exception {
- int removeSize = mContext.getResources().getInteger(
+ // Cast to long to mock RemoteViews.estimateMemoryUsage which returns long.
+ long removeSize = mContext.getResources().getInteger(
com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
RemoteViews rv = mock(RemoteViews.class);
@@ -17570,7 +17577,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
NotificationManagerService.WorkerHandler.class);
mService.setHandler(handler);
when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
Bundle signals = new Bundle();
signals.putInt(KEY_TYPE, TYPE_NEWS);
@@ -17614,7 +17621,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
NotificationManagerService.WorkerHandler.class);
mService.setHandler(handler);
when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
Bundle signals = new Bundle();
signals.putInt(KEY_TYPE, TYPE_NEWS);
@@ -17630,7 +17637,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertThat(r.getChannel().getId()).isEqualTo(NEWS_ID);
// When we block adjustments for this package
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(false);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(false);
signals.putInt(KEY_TYPE, TYPE_PROMOTION);
mBinderService.applyAdjustmentFromAssistant(null, adjustment);
@@ -17952,15 +17959,16 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
@EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
FLAG_NOTIFICATION_FORCE_GROUPING,
- FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION})
- public void testUnbundleNotification_ungrouped_restoresOriginalChannel() throws Exception {
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testUnclassifyNotification_ungrouped_restoresOriginalChannel() throws Exception {
NotificationManagerService.WorkerHandler handler = mock(
NotificationManagerService.WorkerHandler.class);
mService.setHandler(handler);
when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
// Post a single notification
final boolean hasOriginalSummary = false;
@@ -17980,9 +17988,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertThat(r.getChannel().getId()).isEqualTo(NEWS_ID);
// Check that the Notification mChannelId is not updated
assertThat(r.getNotification().getChannelId()).isEqualTo(TEST_CHANNEL_ID);
+ // Check that the bundleType is updated
+ assertThat(r.getBundleType()).isEqualTo(Adjustment.TYPE_NEWS);
- // Unbundle the notification
- mService.mNotificationDelegate.unbundleNotification(keyToUnbundle);
+ // Unclassify the notification
+ mService.unclassifyNotification(keyToUnbundle);
// Check that the original channel was restored
assertThat(r.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
@@ -17992,15 +18002,16 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
@EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
FLAG_NOTIFICATION_FORCE_GROUPING,
- FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION})
- public void testUnbundleNotification_grouped_restoresOriginalChannel() throws Exception {
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testUnclassifyNotification_grouped_restoresOriginalChannel() throws Exception {
NotificationManagerService.WorkerHandler handler = mock(
NotificationManagerService.WorkerHandler.class);
mService.setHandler(handler);
when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
// Post grouped notifications
final String originalGroupName = "originalGroup";
@@ -18028,9 +18039,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
waitForIdle();
r1.applyAdjustments();
assertThat(r1.getChannel().getId()).isEqualTo(NEWS_ID);
+ assertThat(r1.getBundleType()).isEqualTo(Adjustment.TYPE_NEWS);
- // Unbundle the notification
- mService.mNotificationDelegate.unbundleNotification(keyToUnbundle);
+ // Unclassify the notification
+ mService.unclassifyNotification(keyToUnbundle);
// Check that the original channel was restored
assertThat(r1.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
@@ -18039,9 +18051,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
@EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
- FLAG_NOTIFICATION_FORCE_GROUPING,
- FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION})
- public void testUnbundleNotification_groupedSummaryCanceled_restoresOriginalChannel()
+ FLAG_NOTIFICATION_FORCE_GROUPING,
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testUnclassifyNotification_groupedSummaryCanceled_restoresOriginalChannel()
throws Exception {
NotificationManagerService.WorkerHandler handler = mock(
NotificationManagerService.WorkerHandler.class);
@@ -18049,7 +18062,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
// Post grouped notifications
final String originalGroupName = "originalGroup";
@@ -18076,13 +18089,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
waitForIdle();
r1.applyAdjustments();
assertThat(r1.getChannel().getId()).isEqualTo(NEWS_ID);
+ assertThat(r1.getBundleType()).isEqualTo(Adjustment.TYPE_NEWS);
// Cancel original summary
final boolean hasOriginalSummary = false;
mService.mSummaryByGroupKey.remove(summary.getGroupKey());
- // Unbundle the notification
- mService.mNotificationDelegate.unbundleNotification(keyToUnbundle);
+ // Unclassify the notification
+ mService.unclassifyNotification(keyToUnbundle);
// Check that the original channel was restored
assertThat(r1.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
@@ -18092,15 +18106,16 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
@EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
FLAG_NOTIFICATION_FORCE_GROUPING,
- FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION})
- public void testRebundleNotification_restoresBundleChannel() throws Exception {
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testReclassifyNotification_restoresBundleChannel() throws Exception {
NotificationManagerService.WorkerHandler handler = mock(
NotificationManagerService.WorkerHandler.class);
mService.setHandler(handler);
when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
- when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
// Post a single notification
final boolean hasOriginalSummary = false;
@@ -18121,18 +18136,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertThat(r.getBundleType()).isEqualTo(Adjustment.TYPE_NEWS);
// Unbundle the notification
- mService.mNotificationDelegate.unbundleNotification(keyToUnbundle);
+ mService.unclassifyNotification(keyToUnbundle);
// Check that the original channel was restored
assertThat(r.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
- assertThat(r.getBundleType()).isEqualTo(Adjustment.TYPE_NEWS);
verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(r), eq(hasOriginalSummary));
Mockito.reset(mRankingHandler);
Mockito.reset(mGroupHelper);
// Rebundle the notification
- mService.mNotificationDelegate.rebundleNotification(keyToUnbundle);
+ mService.reclassifyNotification(keyToUnbundle);
// Actually apply the adjustments
doAnswer(invocationOnMock -> {
@@ -18148,4 +18162,405 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertThat(r.getChannel().getId()).isEqualTo(NEWS_ID);
}
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+ FLAG_NOTIFICATION_FORCE_GROUPING,
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testDisallowTypeAdj_unclassifiesAllNotifications() throws Exception {
+ NotificationManagerService.WorkerHandler handler = mock(
+ NotificationManagerService.WorkerHandler.class);
+ mService.setHandler(handler);
+ when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+ when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
+
+ // Post some notifications and classify in different bundles
+ final int numNotifications = NotificationChannel.SYSTEM_RESERVED_IDS.size();
+ for (int i = 0; i < numNotifications; i++) {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, mUserId);
+ mService.addNotification(r);
+ Bundle signals = new Bundle();
+ final int adjustmentType = i + 1;
+ signals.putInt(Adjustment.KEY_TYPE, adjustmentType);
+ Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
+ "", r.getUser().getIdentifier());
+ mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+ waitForIdle();
+ r.applyAdjustments();
+ r.setBundleType(adjustmentType);
+ // Check that the NotificationRecord channel is updated
+ assertThat(r.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ assertThat(r.getBundleType()).isEqualTo(adjustmentType);
+ }
+
+ // Disallow KEY_TYPE adjustment
+ mBinderService.disallowAssistantAdjustment(Adjustment.KEY_TYPE);
+ waitForIdle();
+
+ //Check that all notifications have been unbundled
+ for (NotificationRecord record : mService.mNotificationList) {
+ // Check that the original channel was restored
+ assertThat(record.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+ verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(record), anyBoolean());
+ }
+
+ // Re-allow KEY_TYPE adjustment
+ Mockito.reset(mRankingHandler);
+ Mockito.reset(mGroupHelper);
+ mBinderService.allowAssistantAdjustment(Adjustment.KEY_TYPE);
+ waitForIdle();
+
+ // Actually apply the adjustments
+ doAnswer(invocationOnMock -> {
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).applyAdjustments();
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).calculateImportance();
+ return null;
+ }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
+ mService.handleRankingSort();
+
+ // Check that the bundle channel was restored for all notifications
+ verify(handler, times(numNotifications)).scheduleSendRankingUpdate();
+ verify(mRankingHandler, times(numNotifications)).requestSort();
+ for (NotificationRecord record : mService.mNotificationList) {
+ assertThat(record.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ }
+ }
+
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+ FLAG_NOTIFICATION_FORCE_GROUPING,
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testDisableBundleAdjustmentByType_unclassifiesNotifications() throws Exception {
+ NotificationManagerService.WorkerHandler handler = mock(
+ NotificationManagerService.WorkerHandler.class);
+ mService.setHandler(handler);
+ when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+ when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
+
+ // Post some notifications and classify in different bundles
+ final int numNotifications = NotificationChannel.SYSTEM_RESERVED_IDS.size();
+ final int numNewsNotifications = 1;
+ for (int i = 0; i < numNotifications; i++) {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, mUserId);
+ mService.addNotification(r);
+ Bundle signals = new Bundle();
+ final int adjustmentType = i + 1;
+ signals.putInt(Adjustment.KEY_TYPE, adjustmentType);
+ Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
+ "", r.getUser().getIdentifier());
+ mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+ waitForIdle();
+ r.applyAdjustments();
+ r.setBundleType(adjustmentType);
+ // Check that the NotificationRecord channel is updated
+ assertThat(r.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ assertThat(r.getBundleType()).isEqualTo(adjustmentType);
+ }
+
+ // Disable TYPE_NEWS bundle
+ mBinderService.setAssistantAdjustmentKeyTypeState(TYPE_NEWS, false);
+ waitForIdle();
+
+ //Check that all notifications classified as TYPE_NEWS have been unbundled
+ for (NotificationRecord record : mService.mNotificationList) {
+ // Check that the original channel was restored
+ // for notifications classified as TYPE_NEWS
+ if (record.getBundleType() == TYPE_NEWS) {
+ assertThat(record.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+ verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(record), anyBoolean());
+ }
+ }
+
+ // Re-enable TYPE_NEWS bundle
+ Mockito.reset(mRankingHandler);
+ Mockito.reset(mGroupHelper);
+ mBinderService.setAssistantAdjustmentKeyTypeState(TYPE_NEWS, true);
+ waitForIdle();
+
+ // Actually apply the adjustments
+ doAnswer(invocationOnMock -> {
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).applyAdjustments();
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).calculateImportance();
+ return null;
+ }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
+ mService.handleRankingSort();
+
+ // Check that the bundle channel was restored
+ verify(mRankingHandler, times(numNewsNotifications)).requestSort();
+ for (NotificationRecord record : mService.mNotificationList) {
+ assertThat(record.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ }
+ }
+
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+ FLAG_NOTIFICATION_FORCE_GROUPING,
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testDisableBundleAdjustmentByPkg_unclassifiesNotifications() throws Exception {
+ NotificationManagerService.WorkerHandler handler = mock(
+ NotificationManagerService.WorkerHandler.class);
+ mService.setHandler(handler);
+ when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+ when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
+
+ // Post some notifications and classify in different bundles
+ final int numNotifications = NotificationChannel.SYSTEM_RESERVED_IDS.size();
+ for (int i = 0; i < numNotifications; i++) {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, mUserId);
+ mService.addNotification(r);
+ Bundle signals = new Bundle();
+ final int adjustmentType = i + 1;
+ signals.putInt(Adjustment.KEY_TYPE, adjustmentType);
+ Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
+ "", r.getUser().getIdentifier());
+ mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+ waitForIdle();
+ r.applyAdjustments();
+ r.setBundleType(adjustmentType);
+ // Check that the NotificationRecord channel is updated
+ assertThat(r.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ assertThat(r.getBundleType()).isEqualTo(adjustmentType);
+ }
+
+ // Disable TYPE_NEWS bundle
+ mBinderService.setAdjustmentSupportedForPackage(KEY_TYPE, mPkg, false);
+ waitForIdle();
+
+ //Check that all notifications were unbundled
+ for (NotificationRecord record : mService.mNotificationList) {
+ assertThat(record.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+ verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(record), anyBoolean());
+ }
+
+ // Re-enable bundles for package
+ Mockito.reset(mRankingHandler);
+ Mockito.reset(mGroupHelper);
+ mBinderService.setAdjustmentSupportedForPackage(KEY_TYPE, mPkg, true);
+ waitForIdle();
+
+ // Actually apply the adjustments
+ doAnswer(invocationOnMock -> {
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).applyAdjustments();
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).calculateImportance();
+ return null;
+ }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
+ mService.handleRankingSort();
+
+ // Check that the bundle channel was restored
+ verify(mRankingHandler, times(numNotifications)).requestSort();
+ for (NotificationRecord record : mService.mNotificationList) {
+ assertThat(record.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ }
+ }
+
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+ FLAG_NOTIFICATION_FORCE_GROUPING,
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testDisableBundleAdjustmentByPkg_unclassifiesEnqueuedNotifications()
+ throws Exception {
+ NotificationManagerService.WorkerHandler handler = mock(
+ NotificationManagerService.WorkerHandler.class);
+ mService.setHandler(handler);
+ when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+ when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
+
+ // Enqueue some notifications and classify in different bundles
+ final int numNotifications = NotificationChannel.SYSTEM_RESERVED_IDS.size();
+ for (int i = 0; i < numNotifications; i++) {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, mUserId);
+ mService.addEnqueuedNotification(r);
+ Bundle signals = new Bundle();
+ final int adjustmentType = i + 1;
+ signals.putInt(Adjustment.KEY_TYPE, adjustmentType);
+ Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
+ "", r.getUser().getIdentifier());
+ mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+ waitForIdle();
+ r.applyAdjustments();
+ r.setBundleType(adjustmentType);
+ // Check that the NotificationRecord channel is updated
+ assertThat(r.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ assertThat(r.getBundleType()).isEqualTo(adjustmentType);
+ }
+
+ // Disable type adjustment for the package
+ mBinderService.setAdjustmentSupportedForPackage(KEY_TYPE, mPkg, false);
+ waitForIdle();
+
+ //Check that all notifications were unbundled
+ for (NotificationRecord record : mService.mEnqueuedNotifications) {
+ assertThat(record.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+ verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(record), anyBoolean());
+ }
+
+ // Re-enable bundles for package
+ Mockito.reset(mRankingHandler);
+ Mockito.reset(mGroupHelper);
+ mBinderService.setAdjustmentSupportedForPackage(KEY_TYPE, mPkg, true);
+ waitForIdle();
+
+ // Actually apply the adjustments
+ doAnswer(invocationOnMock -> {
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).applyAdjustments();
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).calculateImportance();
+ return null;
+ }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
+ mService.handleRankingSort();
+
+ // Check that the bundle channel was restored
+ verify(mRankingHandler, times(numNotifications)).requestSort();
+ for (NotificationRecord record : mService.mEnqueuedNotifications) {
+ record.applyAdjustments();
+ assertThat(record.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ }
+ }
+
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+ FLAG_NOTIFICATION_FORCE_GROUPING,
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testDisableBundleAdjustmentByType_unclassifiesEnqueuedNotifications()
+ throws Exception {
+ NotificationManagerService.WorkerHandler handler = mock(
+ NotificationManagerService.WorkerHandler.class);
+ mService.setHandler(handler);
+ when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+ when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
+
+ // Enqueue some notifications and classify in different bundles
+ final int numNotifications = NotificationChannel.SYSTEM_RESERVED_IDS.size();
+ final int numNewsNotifications = 1;
+ for (int i = 0; i < numNotifications; i++) {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, mUserId);
+ mService.addEnqueuedNotification(r);
+ Bundle signals = new Bundle();
+ final int adjustmentType = i + 1;
+ signals.putInt(Adjustment.KEY_TYPE, adjustmentType);
+ Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
+ "", r.getUser().getIdentifier());
+ mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+ waitForIdle();
+ r.applyAdjustments();
+ r.setBundleType(adjustmentType);
+ // Check that the NotificationRecord channel is updated
+ assertThat(r.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ assertThat(r.getBundleType()).isEqualTo(adjustmentType);
+ }
+
+ // Disable TYPE_NEWS bundle
+ mBinderService.setAssistantAdjustmentKeyTypeState(TYPE_NEWS, false);
+ waitForIdle();
+
+ //Check that all notifications were unbundled
+ for (NotificationRecord record : mService.mEnqueuedNotifications) {
+ // Check that the original channel was restored
+ // for notifications classified as TYPE_NEWS
+ if (record.getBundleType() == TYPE_NEWS) {
+ assertThat(record.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+ verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(record), anyBoolean());
+ }
+ }
+
+ // Re-enable bundles for package
+ Mockito.reset(mRankingHandler);
+ Mockito.reset(mGroupHelper);
+ mBinderService.setAssistantAdjustmentKeyTypeState(TYPE_NEWS, true);
+ waitForIdle();
+
+ // Actually apply the adjustments
+ doAnswer(invocationOnMock -> {
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).applyAdjustments();
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).calculateImportance();
+ return null;
+ }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
+ mService.handleRankingSort();
+
+ // Check that the bundle channel was restored
+ verify(mRankingHandler, times(numNewsNotifications)).requestSort();
+ for (NotificationRecord record : mService.mEnqueuedNotifications) {
+ record.applyAdjustments();
+ assertThat(record.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ }
+ }
+
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+ FLAG_NOTIFICATION_FORCE_GROUPING,
+ FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
+ android.app.Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
+ public void testDisallowTypeAdj_unclassifiesAllEnqueuedNotifications() throws Exception {
+ NotificationManagerService.WorkerHandler handler = mock(
+ NotificationManagerService.WorkerHandler.class);
+ mService.setHandler(handler);
+ when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+ when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+ when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+ when(mAssistants.isAdjustmentAllowedForPackage(anyString(), anyString())).thenReturn(true);
+
+ // Enqueue some notifications and classify in different bundles
+ final int numNotifications = NotificationChannel.SYSTEM_RESERVED_IDS.size();
+ for (int i = 0; i < numNotifications; i++) {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, mUserId);
+ mService.addEnqueuedNotification(r);
+ Bundle signals = new Bundle();
+ final int adjustmentType = i + 1;
+ signals.putInt(Adjustment.KEY_TYPE, adjustmentType);
+ Adjustment adjustment = new Adjustment(r.getSbn().getPackageName(), r.getKey(), signals,
+ "", r.getUser().getIdentifier());
+ mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+ waitForIdle();
+ r.applyAdjustments();
+ r.setBundleType(adjustmentType);
+ // Check that the NotificationRecord channel is updated
+ assertThat(r.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ assertThat(r.getBundleType()).isEqualTo(adjustmentType);
+ }
+
+ // Disable KEY_TYPE adjustment
+ mBinderService.disallowAssistantAdjustment(Adjustment.KEY_TYPE);
+ waitForIdle();
+
+ //Check that all notifications were unbundled
+ for (NotificationRecord record : mService.mEnqueuedNotifications) {
+ assertThat(record.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+ verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(record), anyBoolean());
+ }
+
+ // Re-enable bundles
+ Mockito.reset(mRankingHandler);
+ Mockito.reset(mGroupHelper);
+ mBinderService.allowAssistantAdjustment(Adjustment.KEY_TYPE);
+ waitForIdle();
+
+ // Actually apply the adjustments
+ doAnswer(invocationOnMock -> {
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).applyAdjustments();
+ ((NotificationRecord) invocationOnMock.getArguments()[0]).calculateImportance();
+ return null;
+ }).when(mRankingHelper).extractSignals(any(NotificationRecord.class));
+ mService.handleRankingSort();
+
+ // Check that the bundle channel was restored
+ verify(mRankingHandler, times(numNotifications)).requestSort();
+ for (NotificationRecord record : mService.mEnqueuedNotifications) {
+ record.applyAdjustments();
+ assertThat(record.getChannel().getId()).isIn(NotificationChannel.SYSTEM_RESERVED_IDS);
+ }
+ }
+
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 704b580a80b0..832ca51ae580 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -260,7 +260,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
return FlagsParameterization.allCombinationsOf(
android.app.Flags.FLAG_API_RICH_ONGOING,
FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_CLASSIFICATION_UI,
- FLAG_MODES_UI);
+ FLAG_MODES_UI, android.app.Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS);
}
public PreferencesHelperTest(FlagsParameterization flags) {
@@ -3381,13 +3381,12 @@ public class PreferencesHelperTest extends UiServiceTestCase {
// user 0 records remain
for (int i = 0; i < user0Uids.length; i++) {
assertEquals(1,
- mHelper.getNotificationChannels(PKG_N_MR1, user0Uids[i], false, true)
- .getList().size());
+ mHelper.getRemovedPkgNotificationChannels(PKG_N_MR1, user0Uids[i]).size());
}
// user 1 records are gone
for (int i = 0; i < user1Uids.length; i++) {
- assertEquals(0, mHelper.getNotificationChannels(PKG_N_MR1, user1Uids[i], false, true)
- .getList().size());
+ assertEquals(0,
+ mHelper.getRemovedPkgNotificationChannels(PKG_N_MR1, user1Uids[i]).size());
}
}
@@ -3402,8 +3401,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
assertTrue(mHelper.onPackagesChanged(true, USER_SYSTEM, new String[]{PKG_N_MR1},
new int[]{UID_N_MR1}));
- assertEquals(0, mHelper.getNotificationChannels(
- PKG_N_MR1, UID_N_MR1, true, true).getList().size());
+ assertEquals(0, mHelper.getRemovedPkgNotificationChannels(PKG_N_MR1, UID_N_MR1).size());
// Not deleted
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false,
@@ -3472,7 +3470,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
assertTrue(mHelper.canShowBadge(PKG_O, UID_O));
assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O));
- assertEquals(0, mHelper.getNotificationChannels(PKG_O, UID_O, true, true).getList().size());
+ assertEquals(0, mHelper.getRemovedPkgNotificationChannels(PKG_O, UID_O).size());
assertEquals(0, mHelper.getNotificationChannelGroups(PKG_O, UID_O).size());
NotificationChannel channel = getChannel();
@@ -6836,38 +6834,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
- @EnableFlags(android.app.Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS)
- public void testGetNotificationChannels_createIfNeeded() {
- // Test setup hasn't created any channels or read package preferences yet.
- // If we ask for notification channels _without_ creating, we should get no result.
- ParceledListSlice<NotificationChannel> channels = mHelper.getNotificationChannels(PKG_N_MR1,
- UID_N_MR1, false, false, /* createPrefsIfNeeded= */ false);
- assertThat(channels.getList().size()).isEqualTo(0);
-
- // If we ask it to create package preferences, we expect the default channel to be created
- // for N_MR1.
- channels = mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false,
- false, /* createPrefsIfNeeded= */ true);
- assertThat(channels.getList().size()).isEqualTo(1);
- assertThat(channels.getList().getFirst().getId()).isEqualTo(
- NotificationChannel.DEFAULT_CHANNEL_ID);
- }
-
- @Test
@DisableFlags(android.app.Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS)
public void testGetNotificationChannels_neverCreatesWhenFlagOff() {
- ParceledListSlice<NotificationChannel> channels;
- try {
- channels = mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false,
- false, /* createPrefsIfNeeded= */ true);
- } catch (Exception e) {
- // Slog.wtf kicks in, presumably
- } finally {
- channels = mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false,
- false, /* createPrefsIfNeeded= */ false);
- assertThat(channels.getList().size()).isEqualTo(0);
- }
-
+ ParceledListSlice<NotificationChannel> channels = mHelper.getNotificationChannels(PKG_N_MR1,
+ UID_N_MR1, false, false);
+ assertThat(channels.getList().size()).isEqualTo(0);
}
// Test version of PreferencesHelper whose only functional difference is that it does not
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
index 16c786b52655..c6b431ce0b18 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
@@ -176,10 +176,10 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_NOTIFICATION,
0},
- {"Meta + Ctrl + S -> Take Screenshot",
- new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_S},
+ {"Meta + S -> Take Screenshot",
+ new int[]{META_KEY, KeyEvent.KEYCODE_S},
KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT, KeyEvent.KEYCODE_S,
- META_ON | CTRL_ON},
+ META_ON},
{"Meta + / -> Open Shortcut Helper", new int[]{META_KEY, KeyEvent.KEYCODE_SLASH},
KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER,
KeyEvent.KEYCODE_SLASH, META_ON},
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 5ac3e483231c..7af4ede05363 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -4461,7 +4461,46 @@ public class SizeCompatTests extends WindowTestsBase {
// are aligned to the top of the parentAppBounds
assertEquals(new Rect(0, notchHeight, 1000, 1200), appBounds);
assertEquals(new Rect(0, 0, 1000, 1200), bounds);
+ }
+
+ @Test
+ @DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
+ public void testInFreeform_boundsSandboxedToAppBounds() {
+ final int dw = 2800;
+ final int dh = 1400;
+ final int notchHeight = 100;
+ final DisplayContent display = new TestDisplayContent.Builder(mAtm, dw, dh)
+ .setNotch(notchHeight)
+ .build();
+ setUpApp(display);
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+ mTask.mDisplayContent.getDefaultTaskDisplayArea()
+ .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
+ mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ Rect appBounds = new Rect(0, 0, 1000, 500);
+ Rect bounds = new Rect(0, 0, 1000, 600);
+ mTask.getWindowConfiguration().setAppBounds(appBounds);
+ mTask.getWindowConfiguration().setBounds(bounds);
+ mActivity.onConfigurationChanged(mTask.getConfiguration());
+
+ // Bounds are sandboxed to appBounds in freeform.
+ assertDownScaled();
+ assertEquals(mActivity.getWindowConfiguration().getAppBounds(),
+ mActivity.getWindowConfiguration().getBounds());
+
+ // Exit freeform.
+ mTask.mDisplayContent.getDefaultTaskDisplayArea()
+ .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ mTask.getWindowConfiguration().setBounds(new Rect(0, 0, dw, dh));
+ mActivity.onConfigurationChanged(mTask.getConfiguration());
+ assertFitted();
+ appBounds = mActivity.getWindowConfiguration().getAppBounds();
+ bounds = mActivity.getWindowConfiguration().getBounds();
+ // Bounds are not sandboxed to appBounds.
+ assertNotEquals(appBounds, bounds);
+ assertEquals(notchHeight, appBounds.top - bounds.top);
}
@Test
diff --git a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
index a03d7e25d4c5..69dd5562711a 100644
--- a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
+++ b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
@@ -112,7 +112,7 @@ public class CallerInfoAsyncQuery {
if (DBG) Log.d(LOG_TAG, "Trying to get current content resolver...");
final int currentUser = ActivityManager.getCurrentUser();
- final int myUser = UserManager.get(context).getProcessUserId();
+ final int myUser = UserHandle.myUserId();
if (DBG) Log.d(LOG_TAG, "myUser=" + myUser + "currentUser=" + currentUser);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6d32303fb13b..73ea68bc3547 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -19380,7 +19380,6 @@ public class TelephonyManager {
*
* @hide
*/
- @FlaggedApi(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY)
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
public void setEnableCellularIdentifierDisclosureNotifications(boolean enable) {
@@ -19406,7 +19405,6 @@ public class TelephonyManager {
*
* @hide
*/
- @FlaggedApi(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY)
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@SystemApi
public boolean isCellularIdentifierDisclosureNotificationsEnabled() {
diff --git a/telephony/java/com/android/internal/telephony/util/WorkerThread.java b/telephony/java/com/android/internal/telephony/util/WorkerThread.java
new file mode 100644
index 000000000000..f5b653656352
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/WorkerThread.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.telephony.util;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.HandlerThread;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+
+/**
+ * Shared singleton worker thread for each process.
+ *
+ * This thread should be used for work that needs to be executed at standard priority
+ * but not on the main thread. This is suitable for handling asynchronous tasks that
+ * are ephemeral or require enough work that they shouldn't block the main thread, but
+ * should not block each other for more than around 100ms.
+ */
+public final class WorkerThread extends HandlerThread {
+ private static volatile WorkerThread sInstance;
+ private static volatile Handler sHandler;
+ private static volatile HandlerExecutor sHandlerExecutor;
+ private static final Object sLock = new Object();
+
+ private CountDownLatch mInitLock = new CountDownLatch(1);
+
+
+ private WorkerThread() {
+ super("android.telephony.worker");
+ }
+
+ private static void ensureThread() {
+ if (sInstance != null) return;
+ synchronized (sLock) {
+ if (sInstance != null) return;
+
+ final WorkerThread tmpThread = new WorkerThread();
+ tmpThread.start();
+
+ try {
+ tmpThread.mInitLock.await();
+ } catch (InterruptedException ignored) {
+ }
+
+
+ sHandler = new Handler(
+ tmpThread.getLooper(),
+ /* callback= */ null,
+ /* async= */ false,
+ /* shared= */ true);
+ sHandlerExecutor = new HandlerExecutor(sHandler);
+ sInstance = tmpThread; // Note: order matters here. sInstance must be assigned last.
+
+ }
+ }
+
+ @Override
+ protected void onLooperPrepared() {
+ mInitLock.countDown();
+ }
+
+ /**
+ * Get the worker thread directly.
+ *
+ * Users of this thread should take care not to block it for extended periods of
+ * time.
+ *
+ * @return a HandlerThread, never null
+ */
+ @NonNull public static HandlerThread get() {
+ ensureThread();
+ return sInstance;
+ }
+
+ /**
+ * Get a Handler that can process Runnables.
+ *
+ * @return a Handler, never null
+ */
+ @NonNull public static Handler getHandler() {
+ ensureThread();
+ return sHandler;
+ }
+
+ /**
+ * Get an Executor that can process Runnables
+ *
+ * @return an Executor, never null
+ */
+ @NonNull public static Executor getExecutor() {
+ ensureThread();
+ return sHandlerExecutor;
+ }
+
+ /**
+ * A method to reset the WorkerThread from scratch.
+ *
+ * This method should only be used for unit testing. In production it would have
+ * catastrophic consequences. Do not ever use this outside of tests.
+ */
+ @VisibleForTesting
+ public static void reset() {
+ synchronized (sLock) {
+ if (sInstance == null) return;
+ sInstance.quitSafely();
+ sInstance = null;
+ sHandler = null;
+ sHandlerExecutor = null;
+ ensureThread();
+ }
+ }
+}
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt
index 8c9ab9aadb8e..def254a65945 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationColdTest.kt
@@ -16,8 +16,6 @@
package com.android.server.wm.flicker.notification
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
import android.platform.test.rule.SettingOverrideRule
import android.provider.Settings
import android.tools.flicker.junit.FlickerParametersRunnerFactory
@@ -26,6 +24,7 @@ import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.flicker.legacy.LegacyFlickerTestFactory
import android.tools.helpers.wakeUpAndGoToHomeScreen
import android.tools.traces.component.ComponentNameMatcher
+import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import org.junit.ClassRule
import org.junit.FixMethodOrder
@@ -46,7 +45,7 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Postsubmit
+@FlakyTest(bugId = 384046002)
open class OpenAppFromLockscreenNotificationColdTest(flicker: LegacyFlickerTest) :
OpenAppFromNotificationColdTest(flicker) {
@@ -107,12 +106,10 @@ open class OpenAppFromLockscreenNotificationColdTest(flicker: LegacyFlickerTest)
override fun navBarWindowIsAlwaysVisible() {}
/** {@inheritDoc} */
- @Postsubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
- @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
flicker.assertWm {
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt
index e595100a2cbe..7da529d7650b 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWarmTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.notification
-import android.platform.test.annotations.Presubmit
import android.platform.test.rule.SettingOverrideRule
import android.provider.Settings
import android.tools.flicker.junit.FlickerParametersRunnerFactory
@@ -46,6 +45,7 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 384046002)
class OpenAppFromLockscreenNotificationWarmTest(flicker: LegacyFlickerTest) :
OpenAppFromNotificationWarmTest(flicker) {
@@ -72,7 +72,6 @@ class OpenAppFromLockscreenNotificationWarmTest(flicker: LegacyFlickerTest) :
* window of the transition, with snapshot or splash screen windows optionally showing first.
*/
@Test
- @Presubmit
fun appWindowBecomesFirstAndOnlyTopWindow() {
flicker.assertWm {
this.hasNoVisibleAppWindow()
@@ -87,7 +86,6 @@ class OpenAppFromLockscreenNotificationWarmTest(flicker: LegacyFlickerTest) :
/** Checks that the screen is locked at the start of the transition */
@Test
- @Presubmit
fun screenLockedStart() {
flicker.assertWmStart { isKeyguardShowing() }
}
@@ -117,7 +115,7 @@ class OpenAppFromLockscreenNotificationWarmTest(flicker: LegacyFlickerTest) :
* Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
* transition
*/
- @Presubmit @Test fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
+ @Test fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
/** {@inheritDoc} */
@Test
@@ -140,7 +138,6 @@ class OpenAppFromLockscreenNotificationWarmTest(flicker: LegacyFlickerTest) :
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
- @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
flicker.assertWm {
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
index fbe1d34272c9..76b43b213132 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromLockscreenNotificationWithOverlayAppTest.kt
@@ -16,8 +16,6 @@
package com.android.server.wm.flicker.notification
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -47,7 +45,7 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Postsubmit
+@FlakyTest(bugId = 384046002)
class OpenAppFromLockscreenNotificationWithOverlayAppTest(flicker: LegacyFlickerTest) :
OpenAppFromLockscreenNotificationColdTest(flicker) {
private val showWhenLockedApp = ShowWhenLockedAppHelper(instrumentation)
@@ -106,7 +104,7 @@ class OpenAppFromLockscreenNotificationWithOverlayAppTest(flicker: LegacyFlicker
}
/** {@inheritDoc} */
- @Presubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
+ @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
/** {@inheritDoc} */
@FlakyTest(bugId = 227143265)
@@ -120,7 +118,6 @@ class OpenAppFromLockscreenNotificationWithOverlayAppTest(flicker: LegacyFlicker
override fun navBarLayerIsVisibleAtStartAndEnd() {}
/** {@inheritDoc} */
- @Presubmit
@Test
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt
index c8ca644dde90..39302d82a5a0 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationColdTest.kt
@@ -16,14 +16,13 @@
package com.android.server.wm.flicker.notification
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.flicker.legacy.LegacyFlickerTestFactory
import android.tools.helpers.wakeUpAndGoToHomeScreen
import android.tools.traces.component.ComponentNameMatcher
+import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
import org.junit.FixMethodOrder
@@ -41,7 +40,7 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Postsubmit
+@FlakyTest(bugId = 384046002)
open class OpenAppFromNotificationColdTest(flicker: LegacyFlickerTest) :
OpenAppFromNotificationWarmTest(flicker) {
/** {@inheritDoc} */
@@ -59,9 +58,9 @@ open class OpenAppFromNotificationColdTest(flicker: LegacyFlickerTest) :
teardown { testApp.exit(wmHelper) }
}
- @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
+ @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
- @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_coldStart()
+ @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_coldStart()
/** {@inheritDoc} */
@Test
@@ -83,7 +82,7 @@ open class OpenAppFromNotificationColdTest(flicker: LegacyFlickerTest) :
* Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
* transition
*/
- @Presubmit @Test open fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
+ @Test open fun statusBarLayerPositionAtEnd() = flicker.statusBarLayerPositionAtEnd()
/** {@inheritDoc} */
@Test
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt
index ad70757a9a4d..f1e1b6f22d59 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppFromNotificationWarmTest.kt
@@ -16,8 +16,6 @@
package com.android.server.wm.flicker.notification
-import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
import android.platform.test.rule.DisableNotificationCooldownSettingRule
import android.tools.flicker.junit.FlickerParametersRunnerFactory
import android.tools.flicker.legacy.FlickerBuilder
@@ -28,6 +26,7 @@ import android.tools.helpers.wakeUpAndGoToHomeScreen
import android.tools.traces.component.ComponentNameMatcher
import android.view.WindowInsets
import android.view.WindowManager
+import androidx.test.filters.FlakyTest
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.NotificationAppHelper
@@ -54,6 +53,7 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 384046002)
open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
OpenAppTransition(flicker) {
override val testApp: NotificationAppHelper = NotificationAppHelper(instrumentation)
@@ -120,23 +120,20 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
// Wait for the app to launch
wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
}
- @Presubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
+ @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
- @Presubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
+ @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
- @Presubmit
@Test
open fun notificationAppWindowVisibleAtEnd() {
flicker.assertWmEnd { this.isAppWindowVisible(testApp) }
}
- @Presubmit
@Test
open fun notificationAppWindowOnTopAtEnd() {
flicker.assertWmEnd { this.isAppWindowOnTop(testApp) }
}
- @Presubmit
@Test
open fun notificationAppLayerVisibleAtEnd() {
flicker.assertLayersEnd { this.isVisible(testApp) }
@@ -148,7 +145,6 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
*
* Note: Large screen only
*/
- @Presubmit
@Test
open fun taskBarWindowIsVisibleAtEnd() {
Assume.assumeTrue(usesTaskbar)
@@ -160,7 +156,6 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
*
* Note: Large screen only
*/
- @Presubmit
@Test
open fun taskBarLayerIsVisibleAtEnd() {
Assume.assumeTrue(usesTaskbar)
@@ -168,7 +163,6 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
}
/** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
- @Presubmit
@Test
open fun navBarLayerPositionAtEnd() {
Assume.assumeFalse(usesTaskbar)
@@ -176,14 +170,12 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
}
/** {@inheritDoc} */
- @Presubmit
@Test
open fun navBarLayerIsVisibleAtEnd() {
Assume.assumeFalse(usesTaskbar)
flicker.navBarLayerIsVisibleAtEnd()
}
- @Presubmit
@Test
open fun navBarWindowIsVisibleAtEnd() {
Assume.assumeFalse(usesTaskbar)
@@ -197,7 +189,6 @@ open class OpenAppFromNotificationWarmTest(flicker: LegacyFlickerTest) :
/** {@inheritDoc} */
@Test
- @Postsubmit
override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
companion object {
diff --git a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt
index 4ba444b0815a..e825af910a38 100644
--- a/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt
+++ b/tests/FlickerTests/Notification/src/com/android/server/wm/flicker/notification/OpenAppTransition.kt
@@ -16,10 +16,10 @@
package com.android.server.wm.flicker.notification
-import android.platform.test.annotations.Presubmit
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.traces.component.ComponentNameMatcher
+import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.BaseTest
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import org.junit.Test
@@ -41,7 +41,7 @@ abstract class OpenAppTransition(flicker: LegacyFlickerTest) : BaseTest(flicker)
* Checks that the [testApp] layer doesn't exist or is invisible at the start of the transition,
* but is created and/or becomes visible during the transition.
*/
- @Presubmit
+ @FlakyTest(bugId = 384046002)
@Test
open fun appLayerBecomesVisible() {
appLayerBecomesVisible_coldStart()
@@ -80,7 +80,7 @@ abstract class OpenAppTransition(flicker: LegacyFlickerTest) : BaseTest(flicker)
* The `isAppWindowInvisible` step is optional because we log once per frame, upon logging, the
* window may be visible or not depending on what was processed until that moment.
*/
- @Presubmit @Test open fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
+ @FlakyTest(bugId = 384046002) @Test open fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
protected fun appWindowBecomesVisible_coldStart() {
flicker.assertWm {
@@ -108,7 +108,7 @@ abstract class OpenAppTransition(flicker: LegacyFlickerTest) : BaseTest(flicker)
* Checks that [testApp] window is not on top at the start of the transition, and then becomes
* the top visible window until the end of the transition.
*/
- @Presubmit
+ @FlakyTest(bugId = 384046002)
@Test
open fun appWindowBecomesTopWindow() {
flicker.assertWm {
@@ -124,7 +124,7 @@ abstract class OpenAppTransition(flicker: LegacyFlickerTest) : BaseTest(flicker)
* Checks that [testApp] window is not on top at the start of the transition, and then becomes
* the top visible window until the end of the transition.
*/
- @Presubmit
+ @FlakyTest(bugId = 384046002)
@Test
open fun appWindowIsTopWindowAtEnd() {
flicker.assertWmEnd { this.isAppWindowOnTop(testApp) }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index 851ce022bd81..03d6ce88ac0c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -18,7 +18,9 @@ package com.android.server.wm.flicker
import android.app.Instrumentation
import android.content.Intent
+import android.os.UserHandle
import android.platform.test.annotations.Presubmit
+import android.provider.Settings
import android.tools.flicker.junit.FlickerBuilderProvider
import android.tools.flicker.legacy.FlickerBuilder
import android.tools.flicker.legacy.LegacyFlickerTest
@@ -45,6 +47,12 @@ constructor(
) {
init {
tapl.setExpectedRotationCheckEnabled(true)
+ Settings.System.putIntForUser(
+ instrumentation.targetContext.contentResolver,
+ Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
+ 0,
+ UserHandle.USER_CURRENT
+ );
}
private val logTag = this::class.java.simpleName
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index eef4e6f58463..36db955c3085 100644
--- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -383,15 +383,14 @@ class KeyGestureControllerTests {
intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
),
TestData(
- "META + CTRL + S -> Take Screenshot",
+ "META + S -> Take Screenshot",
intArrayOf(
KeyEvent.KEYCODE_META_LEFT,
- KeyEvent.KEYCODE_CTRL_LEFT,
KeyEvent.KEYCODE_S
),
KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT,
intArrayOf(KeyEvent.KEYCODE_S),
- KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+ KeyEvent.META_META_ON,
intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
),
TestData(
diff --git a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index d6654cceb458..4440a839caef 100644
--- a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -28,6 +28,8 @@ import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.hardware.input.KeyboardLayout
import android.hardware.input.KeyboardLayoutSelectionResult
+import android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE
+import android.hardware.input.KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_USER
import android.icu.util.ULocale
import android.os.Bundle
import android.os.test.TestLooper
@@ -281,6 +283,41 @@ class KeyboardLayoutManagerTests {
}
@Test
+ fun testGetSetKeyboardLayoutOverrideForInputDevice() {
+ val imeSubtype = createImeSubtype()
+
+ keyboardLayoutManager.setKeyboardLayoutOverrideForInputDevice(
+ keyboardDevice.identifier,
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ var result =
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+ )
+ assertEquals(LAYOUT_SELECTION_CRITERIA_DEVICE, result.selectionCriteria)
+ assertEquals(
+ "getKeyboardLayoutForInputDevice API should return the set layout",
+ ENGLISH_UK_LAYOUT_DESCRIPTOR,
+ result.layoutDescriptor
+ )
+
+ // This should replace the overriding layout set above
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ result = keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+ )
+ assertEquals(LAYOUT_SELECTION_CRITERIA_USER, result.selectionCriteria)
+ assertEquals(
+ "getKeyboardLayoutForInputDevice API should return the user set layout",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ result.layoutDescriptor
+ )
+ }
+
+ @Test
fun testGetKeyboardLayoutListForInputDevice() {
// Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
var keyboardLayouts =
diff --git a/tests/testables/src/android/testing/OWNERS b/tests/testables/src/android/testing/OWNERS
new file mode 100644
index 000000000000..f31666b43654
--- /dev/null
+++ b/tests/testables/src/android/testing/OWNERS
@@ -0,0 +1,2 @@
+# MessageQueue-related classes
+per-file TestableLooper.java = mfasheh@google.com, shayba@google.com
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index be5c84c0353c..3ee6dc48bfa3 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -42,6 +42,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
* and provide an easy annotation for use with tests.
*
* @see TestableLooperTest TestableLooperTest for examples.
+ *
+ * @deprecated Use {@link android.os.TestLooperManager} or {@link
+ * org.robolectric.shadows.ShadowLooper} instead.
+ * This class is not actively maintained.
+ * Both of the recommended alternatives allow fine control of execution.
+ * The Robolectric class also allows advancing time.
*/
public class TestableLooper {
diff --git a/tests/utils/testutils/java/android/os/test/OWNERS b/tests/utils/testutils/java/android/os/test/OWNERS
index 3a9129e1bb69..6448261102fa 100644
--- a/tests/utils/testutils/java/android/os/test/OWNERS
+++ b/tests/utils/testutils/java/android/os/test/OWNERS
@@ -1 +1,4 @@
per-file FakePermissionEnforcer.java = file:/tests/EnforcePermission/OWNERS
+
+# MessageQueue-related classes
+per-file TestLooper.java = mfasheh@google.com, shayba@google.com
diff --git a/tests/utils/testutils/java/android/os/test/TestLooper.java b/tests/utils/testutils/java/android/os/test/TestLooper.java
index 56b0a25ed2dd..83d22d923c78 100644
--- a/tests/utils/testutils/java/android/os/test/TestLooper.java
+++ b/tests/utils/testutils/java/android/os/test/TestLooper.java
@@ -33,9 +33,15 @@ import java.lang.reflect.Method;
import java.util.concurrent.Executor;
/**
- * Creates a looper whose message queue can be manipulated
- * This allows testing code that uses a looper to dispatch messages in a deterministic manner
- * Creating a TestLooper will also install it as the looper for the current thread
+ * Creates a looper whose message queue can be manipulated This allows testing code that uses a
+ * looper to dispatch messages in a deterministic manner Creating a TestLooper will also install it
+ * as the looper for the current thread
+ *
+ * @deprecated Use {@link android.os.TestLooperManager} or {@link
+ * org.robolectric.shadows.ShadowLooper} instead.
+ * This class is not actively maintained.
+ * Both of the recommended alternatives allow fine control of execution.
+ * The Robolectric class also allows advancing time.
*/
public class TestLooper {
protected final Looper mLooper;