summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AconfigFlags.bp5
-rw-r--r--api/StubLibraries.bp6
-rw-r--r--core/api/current.txt17
-rw-r--r--core/api/system-current.txt7
-rw-r--r--core/api/test-current.txt4
-rw-r--r--core/java/android/app/ActivityTaskManager.java14
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl6
-rw-r--r--core/java/android/app/StatusBarManager.java57
-rw-r--r--core/java/android/app/UiAutomation.java9
-rw-r--r--core/java/android/app/notification.aconfig14
-rw-r--r--core/java/android/app/supervision/flags.aconfig8
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java4
-rw-r--r--core/java/android/content/pm/UserInfo.java6
-rw-r--r--core/java/android/hardware/camera2/params/SharedSessionConfiguration.java2
-rw-r--r--core/java/android/inputmethodservice/NavigationBarController.java6
-rw-r--r--core/java/android/inputmethodservice/navigationbar/NavigationBarView.java22
-rw-r--r--core/java/android/os/Binder.java16
-rw-r--r--core/java/android/os/CombinedMessageQueue/MessageQueue.java43
-rw-r--r--core/java/android/os/UserManager.java14
-rw-r--r--core/java/android/service/notification/Adjustment.java9
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java24
-rw-r--r--core/java/android/widget/RemoteViews.java11
-rw-r--r--core/java/android/window/DesktopExperienceFlags.java124
-rw-r--r--core/java/android/window/DesktopModeFlags.java9
-rw-r--r--core/java/android/window/OWNERS1
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig12
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl8
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl8
-rw-r--r--core/jni/android_util_Binder.cpp34
-rw-r--r--core/res/res/values/public-final.xml82
-rw-r--r--core/res/res/values/public-staging.xml69
-rw-r--r--core/tests/FileSystemUtilsTest/Android.bp32
-rw-r--r--core/tests/FileSystemUtilsTest/AndroidTest.xml1
-rw-r--r--core/tests/FileSystemUtilsTest/app_with_4kb_elf/app_with_4kb_elf.xml1
-rw-r--r--core/tests/FileSystemUtilsTest/app_with_4kb_elf/page_size_compat_disabled.xml36
-rw-r--r--core/tests/FileSystemUtilsTest/app_with_4kb_elf/src/android/test/pagesizecompat/PageSizeCompatTest.java15
-rw-r--r--core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java43
-rw-r--r--core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java20
-rw-r--r--core/tests/coretests/src/android/window/DesktopExperienceFlagsTest.java164
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt4
-rw-r--r--libs/WindowManager/Shell/res/values/config.xml3
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java2
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt (renamed from libs/WindowManager/Shell/src/com/android/wm/shell/compatui/DesktopModeCompatPolicy.kt)32
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java115
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java199
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt5
-rw-r--r--libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/CopyContentInSplit.kt2
-rw-r--r--libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByDivider.kt2
-rw-r--r--libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByGoHome.kt2
-rw-r--r--libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DragDividerToResize.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java29
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt (renamed from libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/DesktopModeCompatPolicyTest.kt)3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt2
-rw-r--r--media/java/android/media/AudioManager.java109
-rw-r--r--media/java/android/media/MediaCodec.java33
-rw-r--r--media/java/android/media/quality/MediaQualityContract.java344
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp4
-rw-r--r--media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java51
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java5
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java17
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java43
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_extra.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_large.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_extra.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_large.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_extra.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_large.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout/settingslib_button_layout.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout/settingslib_number_button.xml3
-rw-r--r--packages/SettingsLib/ButtonPreference/res/layout/settingslib_section_button.xml3
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt4
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt5
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt3
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig29
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt85
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt15
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/DefaultShortcutCategoriesRepositoryTest.kt20
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt50
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java36
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ModesTileTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt23
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractorTest.kt13
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt1
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt5
-rw-r--r--packages/SystemUI/res/layout/volume_dialog_slider.xml8
-rw-r--r--packages/SystemUI/res/values-xlarge-land/config.xml1
-rw-r--r--packages/SystemUI/res/values/config.xml5
-rw-r--r--packages/SystemUI/res/values/strings.xml14
-rw-r--r--packages/SystemUI/res/values/styles.xml10
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java42
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java18
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierText.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/AccessibilityShortcutsSource.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt176
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/SessionTracker.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractor.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTransitionAnimatorController.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractor.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/shared/model/SliderInputEvent.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinder.kt82
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt249
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/compose/VolumeDialogSliderTrack.kt347
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModel.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt51
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/haptics/ui/VolumeHapticsConfigsProvider.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt70
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt9
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractorKosmos.kt39
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessKosmos.kt5
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessWrapperFake.kt3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java10
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponentKosmos.kt5
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinderKosmos.kt33
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinderKosmos.kt6
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModelKosmos.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt4
-rwxr-xr-xravenwood/scripts/pta-framework.sh3
-rw-r--r--ravenwood/texts/ravenwood-framework-policies.txt2
-rw-r--r--ravenwood/texts/ravenwood-standard-options.txt3
-rw-r--r--ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt3
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java1
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java34
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java (renamed from services/accessibility/java/com/android/server/accessibility/AutoclickController.java)7
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickIndicatorView.java (renamed from services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java)2
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java10
-rw-r--r--services/core/java/com/android/server/am/BroadcastController.java2
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java12
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java89
-rw-r--r--services/core/java/com/android/server/audio/AudioManagerShellCommand.java39
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java69
-rw-r--r--services/core/java/com/android/server/audio/PlaybackActivityMonitor.java67
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java3
-rw-r--r--services/core/java/com/android/server/input/InputGestureManager.java10
-rw-r--r--services/core/java/com/android/server/media/quality/MediaQualityService.java343
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java9
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java17
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecordExtractorData.java11
-rw-r--r--services/core/java/com/android/server/pm/DexOptHelper.java99
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java1
-rw-r--r--services/core/java/com/android/server/pm/UserManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java6
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java28
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java10
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java64
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java10
-rw-r--r--services/core/java/com/android/server/wm/Transition.java11
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java34
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java87
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/accessibility/AutoclickControllerTest.java)4
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/DeviceVolumeBehaviorTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java6
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java10
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java55
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/DeferredKeyActionExecutorTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java2
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl1
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java4
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java4
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/RecentTasksUtils.kt (renamed from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/RecentTasksUtils.kt)4
-rw-r--r--tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt24
253 files changed, 4410 insertions, 1413 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 302168d845fa..834398e5c2c2 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -824,6 +824,11 @@ java_aconfig_library {
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+cc_aconfig_library {
+ name: "android.media.tv.flags-aconfig-cc",
+ aconfig_declarations: "android.media.tv.flags-aconfig",
+}
+
// Permissions
aconfig_declarations {
name: "android.permission.flags-aconfig",
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index 787fdee6ee16..3314b4aa0d71 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -648,7 +648,7 @@ java_api_library {
java_api_library {
name: "android-non-updatable.stubs.module_lib.from-text",
- api_surface: "module_lib",
+ api_surface: "module-lib",
api_contributions: [
"api-stubs-docs-non-updatable.api.contribution",
"system-api-stubs-docs-non-updatable.api.contribution",
@@ -668,7 +668,7 @@ java_api_library {
// generated from this module, as this module is strictly used for hiddenapi only.
java_api_library {
name: "android-non-updatable.stubs.test_module_lib",
- api_surface: "module_lib",
+ api_surface: "module-lib",
api_contributions: [
"api-stubs-docs-non-updatable.api.contribution",
"system-api-stubs-docs-non-updatable.api.contribution",
@@ -689,7 +689,7 @@ java_api_library {
java_api_library {
name: "android-non-updatable.stubs.system_server.from-text",
- api_surface: "system_server",
+ api_surface: "system-server",
api_contributions: [
"api-stubs-docs-non-updatable.api.contribution",
"system-api-stubs-docs-non-updatable.api.contribution",
diff --git a/core/api/current.txt b/core/api/current.txt
index 6964866db7f3..3883a9667355 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -452,7 +452,7 @@ package android {
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
- field @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public static final int adServiceTypes;
+ field @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public static final int adServiceTypes = 16844452; // 0x10106a4
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -1017,7 +1017,7 @@ package android {
field public static final int insetRight = 16843192; // 0x10101b8
field public static final int insetTop = 16843193; // 0x10101b9
field public static final int installLocation = 16843447; // 0x10102b7
- field @FlaggedApi("android.security.enable_intent_matching_flags") public static final int intentMatchingFlags;
+ field @FlaggedApi("android.security.enable_intent_matching_flags") public static final int intentMatchingFlags = 16844457; // 0x10106a9
field public static final int interactiveUiTimeout = 16844181; // 0x1010595
field public static final int interpolator = 16843073; // 0x1010141
field public static final int intro = 16844395; // 0x101066b
@@ -1072,7 +1072,7 @@ package android {
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
- field @FlaggedApi("android.view.inputmethod.ime_switcher_revamp_api") public static final int languageSettingsActivity;
+ field @FlaggedApi("android.view.inputmethod.ime_switcher_revamp_api") public static final int languageSettingsActivity = 16844453; // 0x10106a5
field public static final int languageTag = 16844040; // 0x1010508
field public static final int largeHeap = 16843610; // 0x101035a
field public static final int largeScreens = 16843398; // 0x1010286
@@ -1085,7 +1085,7 @@ package android {
field public static final int layout = 16842994; // 0x10100f2
field public static final int layoutAnimation = 16842988; // 0x10100ec
field public static final int layoutDirection = 16843698; // 0x10103b2
- field @FlaggedApi("android.view.inputmethod.ime_switcher_revamp_api") public static final int layoutLabel;
+ field @FlaggedApi("android.view.inputmethod.ime_switcher_revamp_api") public static final int layoutLabel = 16844458; // 0x10106aa
field public static final int layoutMode = 16843738; // 0x10103da
field public static final int layout_above = 16843140; // 0x1010184
field public static final int layout_alignBaseline = 16843142; // 0x1010186
@@ -1207,7 +1207,7 @@ package android {
field public static final int minResizeHeight = 16843670; // 0x1010396
field public static final int minResizeWidth = 16843669; // 0x1010395
field public static final int minSdkVersion = 16843276; // 0x101020c
- field @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static final int minSdkVersionFull;
+ field @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static final int minSdkVersionFull = 16844461; // 0x10106ad
field public static final int minWidth = 16843071; // 0x101013f
field public static final int minimumHorizontalAngle = 16843901; // 0x101047d
field public static final int minimumVerticalAngle = 16843902; // 0x101047e
@@ -1282,7 +1282,7 @@ package android {
field public static final int paddingStart = 16843699; // 0x10103b3
field public static final int paddingTop = 16842967; // 0x10100d7
field public static final int paddingVertical = 16844094; // 0x101053e
- field @FlaggedApi("android.content.pm.app_compat_option_16kb") public static final int pageSizeCompat;
+ field @FlaggedApi("android.content.pm.app_compat_option_16kb") public static final int pageSizeCompat = 16844459; // 0x10106ab
field public static final int panelBackground = 16842846; // 0x101005e
field public static final int panelColorBackground = 16842849; // 0x1010061
field public static final int panelColorForeground = 16842848; // 0x1010060
@@ -1624,7 +1624,7 @@ package android {
field public static final int summaryColumn = 16843426; // 0x10102a2
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
- field @FlaggedApi("android.view.accessibility.supplemental_description") public static final int supplementalDescription;
+ field @FlaggedApi("android.view.accessibility.supplemental_description") public static final int supplementalDescription = 16844456; // 0x10106a8
field public static final int supportedTypes = 16844369; // 0x1010651
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsBatteryGameMode = 16844374; // 0x1010656
@@ -1871,7 +1871,7 @@ package android {
field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
- field @FlaggedApi("android.nfc.nfc_associated_role_services") public static final int wantsRoleHolderPriority;
+ field @FlaggedApi("android.nfc.nfc_associated_role_services") public static final int wantsRoleHolderPriority = 16844460; // 0x10106ac
field public static final int webTextViewStyle = 16843449; // 0x10102b9
field public static final int webViewStyle = 16842885; // 0x1010085
field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -42267,6 +42267,7 @@ package android.service.notification {
method public int getRank();
method @NonNull public java.util.List<android.app.Notification.Action> getSmartActions();
method @NonNull public java.util.List<java.lang.CharSequence> getSmartReplies();
+ method @FlaggedApi("android.app.nm_summarization") @Nullable public String getSummarization();
method public int getSuppressedVisualEffects();
method public int getUserSentiment();
method public boolean isAmbient();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 937a9ffaf210..8a5276c1ce08 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -464,7 +464,7 @@ package android {
public static final class R.attr {
field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
- field @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled") public static final int backgroundPermission;
+ field @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled") public static final int backgroundPermission = 16844455; // 0x10106a7
field @FlaggedApi("android.content.res.manifest_flagging") public static final int featureFlag = 16844428; // 0x101068c
field public static final int gameSessionService = 16844373; // 0x1010655
field public static final int hotwordDetectionService = 16844326; // 0x1010626
@@ -543,7 +543,7 @@ package android {
field public static final int config_systemCallStreaming = 17039431; // 0x1040047
field public static final int config_systemCompanionDeviceProvider = 17039417; // 0x1040039
field public static final int config_systemContacts = 17039403; // 0x104002b
- field @FlaggedApi("android.content.pm.sdk_dependency_installer") public static final int config_systemDependencyInstaller;
+ field @FlaggedApi("android.content.pm.sdk_dependency_installer") public static final int config_systemDependencyInstaller = 17039434; // 0x104004a
field public static final int config_systemFinancedDeviceController = 17039430; // 0x1040046
field public static final int config_systemGallery = 17039399; // 0x1040027
field public static final int config_systemNotificationIntelligence = 17039413; // 0x1040035
@@ -555,7 +555,7 @@ package android {
field public static final int config_systemTextIntelligence = 17039414; // 0x1040036
field public static final int config_systemUi = 17039418; // 0x104003a
field public static final int config_systemUiIntelligence = 17039410; // 0x1040032
- field @FlaggedApi("android.permission.flags.system_vendor_intelligence_role_enabled") public static final int config_systemVendorIntelligence;
+ field @FlaggedApi("android.permission.flags.system_vendor_intelligence_role_enabled") public static final int config_systemVendorIntelligence = 17039435; // 0x104004b
field public static final int config_systemVisualIntelligence = 17039415; // 0x1040037
field public static final int config_systemWearHealthService = 17039428; // 0x1040044
field public static final int config_systemWellbeing = 17039408; // 0x1040030
@@ -13446,6 +13446,7 @@ package android.service.notification {
field public static final String KEY_RANKING_SCORE = "key_ranking_score";
field public static final String KEY_SENSITIVE_CONTENT = "key_sensitive_content";
field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
+ field @FlaggedApi("android.app.nm_summarization") public static final String KEY_SUMMARIZATION = "key_summarization";
field public static final String KEY_TEXT_REPLIES = "key_text_replies";
field @FlaggedApi("android.service.notification.notification_classification") public static final String KEY_TYPE = "key_type";
field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index f06bd48a8cd8..e2fe5062d356 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1634,6 +1634,10 @@ package android.hardware.camera2.params {
method public void setColorSpace(@NonNull android.graphics.ColorSpace.Named);
}
+ @FlaggedApi("com.android.internal.camera.flags.camera_multi_client") public final class SharedSessionConfiguration {
+ ctor public SharedSessionConfiguration(int, @NonNull long[]);
+ }
+
}
package android.hardware.devicestate {
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 16dcf2ad7e45..8d20e46c7df8 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -25,6 +25,7 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -483,6 +484,19 @@ public class ActivityTaskManager {
}
/**
+ * @return Whether the app could be universal resizeable (assuming it's on a large screen and
+ * ignoring possible overrides)
+ * @hide
+ */
+ public boolean canBeUniversalResizeable(@NonNull ApplicationInfo appInfo) {
+ try {
+ return getService().canBeUniversalResizeable(appInfo);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Detaches the navigation bar from the app it was attached to during a transition.
* @hide
*/
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index c6f62a21641d..4b1afa517122 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -158,6 +158,12 @@ interface IActivityTaskManager {
void reportAssistContextExtras(in IBinder assistToken, in Bundle extras,
in AssistStructure structure, in AssistContent content, in Uri referrer);
+ /**
+ * @return whether the app could be universal resizeable (assuming it's on a large screen and
+ * ignoring possible overrides)
+ */
+ boolean canBeUniversalResizeable(in ApplicationInfo appInfo);
+
void setFocusedRootTask(int taskId);
ActivityTaskManager.RootTaskInfo getFocusedRootTaskInfo();
Rect getTaskBounds(int taskId);
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index b7285c38290c..7454c44997d6 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -60,6 +60,7 @@ import com.android.internal.statusbar.NotificationVisibility;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -195,12 +196,40 @@ public class StatusBarManager {
*/
private static final int DEFAULT_SIM_LOCKED_DISABLED_FLAGS = DISABLE_EXPAND;
- /** @hide */
- public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0;
- /** @hide */
- public static final int NAVIGATION_HINT_IME_SHOWN = 1 << 1;
- /** @hide */
- public static final int NAVIGATION_HINT_IME_SWITCHER_SHOWN = 1 << 2;
+ /**
+ * 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
+ * {@link android.inputmethodservice.InputMethodService.BackDispositionMode backDispositionMode}
+ * set by the IME.
+ *
+ * @hide
+ */
+ public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0;
+ /**
+ * The IME is visible.
+ *
+ * @hide
+ */
+ public static final int NAVIGATION_HINT_IME_SHOWN = 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_SHOWN = 1 << 2;
+ /**
+ * Navigation bar flags related to the IME state.
+ *
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "NAVIGATION_HINT_" }, value = {
+ NAVIGATION_HINT_BACK_ALT,
+ NAVIGATION_HINT_IME_SHOWN,
+ NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NavigationHint {}
/** @hide */
public static final int WINDOW_STATUS_BAR = 1;
@@ -1325,6 +1354,22 @@ 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");
+ }
+ if ((hints & NAVIGATION_HINT_IME_SHOWN) != 0) {
+ hintStrings.add("NAVIGATION_HINT_IME_SHOWN");
+ }
+ if ((hints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0) {
+ hintStrings.add("NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN");
+ }
+ return String.join(" | ", hintStrings);
+ }
+
+ /** @hide */
public static String windowStateToString(int state) {
if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
if (state == WINDOW_STATE_HIDDEN) return "WINDOW_STATE_HIDDEN";
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 1035d8b93881..063055eb4917 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1146,9 +1146,9 @@ public final class UiAutomation {
executionStartTimeMillis = SystemClock.uptimeMillis();
eventQueueStartIndex = mEventQueue.size();
}
- if (DEBUG) {
- Log.d(LOG_TAG, "executeAndWaitForEvent: watchersCount=" + watchersDepth
- + ", eventQueueStartIndex=" + eventQueueStartIndex);
+ if (VERBOSE) {
+ Log.v(LOG_TAG, "executeAndWaitForEvent starts at depth=" + watchersDepth + ", "
+ + "command=" + command + ", filter=" + filter + ", timeout=" + timeoutMillis);
}
try {
@@ -1199,6 +1199,9 @@ public final class UiAutomation {
}
mLock.notifyAll();
}
+ if (VERBOSE) {
+ Log.v(LOG_TAG, "executeAndWaitForEvent ends at depth=" + watchersDepth);
+ }
}
}
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index 914ca73f1ce4..a4a6a55fc9ab 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -310,3 +310,17 @@ flag {
description: "removes sbnholder from NLS"
bug: "362981561"
}
+
+flag {
+ name: "nm_summarization"
+ namespace: "systemui"
+ description: "Allows the NAS to summarize notifications"
+ bug: "390417189"
+}
+
+flag {
+ name: "nm_summarization_ui"
+ namespace: "systemui"
+ description: "Shows summarized notifications in the UI"
+ bug: "390217880"
+}
diff --git a/core/java/android/app/supervision/flags.aconfig b/core/java/android/app/supervision/flags.aconfig
index 19fdbb7214d0..232883cbfe00 100644
--- a/core/java/android/app/supervision/flags.aconfig
+++ b/core/java/android/app/supervision/flags.aconfig
@@ -56,3 +56,11 @@ flag {
description: "Flag to enable the App Approval settings in Android settings UI"
bug: "390185393"
}
+
+flag {
+ name: "enable_supervision_pin_recovery_screen"
+ is_exported: true
+ namespace: "supervision"
+ description: "Flag that enables the Supervision pin recovery screen with Supervision settings entry point"
+ bug: "390500290"
+}
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index df1028e9e04c..b9b5c6a8bbc3 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityOptions;
-import android.app.LoadedApk;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -753,9 +752,6 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW
*/
protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
try {
- ApplicationInfo expectedAppInfo = mInfo.providerInfo.applicationInfo;
- LoadedApk.checkAndUpdateApkPaths(expectedAppInfo);
- // Return if cloned successfully, otherwise default
Context newContext = mContext.createApplicationContext(
mInfo.providerInfo.applicationInfo,
Context.CONTEXT_RESTRICTED);
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 8a3a3ad56a7b..582a1a9442ce 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -183,6 +183,12 @@ public class UserInfo implements Parcelable {
*
* <p>This is not necessarily the system user. For example, it will not be the system user on
* devices for which {@link UserManager#isHeadlessSystemUserMode()} returns true.
+ *
+ * <p>NB: Features should ideally not limit functionality to the main user. Ideally, they
+ * should either work for all users or for all admin users. If a feature should only work for
+ * select users, its determination of which user should be done intelligently or be
+ * customizable. Not all devices support a main user, and the idea of singling out one user as
+ * special is contrary to overall multiuser goals.
*/
public static final int FLAG_MAIN = 0x00004000;
diff --git a/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java b/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java
index 365f870ba22d..b40c7d35c06b 100644
--- a/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java
+++ b/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.graphics.ColorSpace;
import android.graphics.ImageFormat.Format;
import android.hardware.DataSpace.NamedDataSpace;
@@ -228,6 +229,7 @@ public final class SharedSessionConfiguration {
*
* @hide
*/
+ @TestApi
public SharedSessionConfiguration(int sharedColorSpace,
@NonNull long[] sharedOutputConfigurations) {
mColorSpace = sharedColorSpace;
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index 019ba0045916..edc5cb7cdf6a 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -18,7 +18,7 @@ package android.inputmethodservice;
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
@@ -245,7 +245,7 @@ final class NavigationBarController {
// TODO(b/213337792): Set NAVIGATION_HINT_IME_SHOWN only when necessary.
final int hints = NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN
| (mShouldShowImeSwitcherWhenImeIsShown
- ? NAVIGATION_HINT_IME_SWITCHER_SHOWN : 0);
+ ? NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN : 0);
navigationBarView.setNavigationIconHints(hints);
navigationBarView.prepareNavButtons(this);
}
@@ -518,7 +518,7 @@ final class NavigationBarController {
// TODO(b/213337792): Set NAVIGATION_HINT_IME_SHOWN only when necessary.
final int hints = NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN
| (mShouldShowImeSwitcherWhenImeIsShown
- ? NAVIGATION_HINT_IME_SWITCHER_SHOWN : 0);
+ ? NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN : 0);
navigationBarView.setNavigationIconHints(hints);
}
} else {
diff --git a/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java b/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java
index e7e46a9482c8..622d5d1b1c5a 100644
--- a/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java
+++ b/core/java/android/inputmethodservice/navigationbar/NavigationBarView.java
@@ -16,6 +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_SHOWN;
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;
@@ -28,6 +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.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
@@ -63,7 +66,8 @@ public final class NavigationBarView extends FrameLayout {
private int mCurrentRotation = -1;
int mDisabledFlags = 0;
- int mNavigationIconHints = StatusBarManager.NAVIGATION_HINT_BACK_ALT;
+ @NavigationHint
+ private int mNavigationIconHints = 0;
private final int mNavBarMode = NAV_BAR_MODE_GESTURAL;
private KeyButtonDrawable mBackIcon;
@@ -241,8 +245,7 @@ public final class NavigationBarView extends FrameLayout {
}
private void orientBackButton(KeyButtonDrawable drawable) {
- final boolean useAltBack =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+ final boolean useAltBack = (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0;
final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
if (drawable.getRotation() == degrees) {
@@ -284,8 +287,10 @@ public final class NavigationBarView extends FrameLayout {
*
* @param hints bit flags defined in {@link StatusBarManager}.
*/
- public void setNavigationIconHints(int hints) {
- if (hints == mNavigationIconHints) return;
+ public void setNavigationIconHints(@NavigationHint int hints) {
+ if (hints == mNavigationIconHints) {
+ return;
+ }
final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
final boolean oldBackAlt =
(mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
@@ -312,9 +317,10 @@ public final class NavigationBarView extends FrameLayout {
getImeSwitchButton().setImageDrawable(mImeSwitcherIcon);
// Update IME button visibility, a11y and rotate button always overrides the appearance
- final boolean imeSwitcherVisible =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN) != 0;
- getImeSwitchButton().setVisibility(imeSwitcherVisible ? View.VISIBLE : View.INVISIBLE);
+ final boolean isImeSwitcherButtonVisible =
+ (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0;
+ getImeSwitchButton()
+ .setVisibility(isImeSwitcherButtonVisible ? View.VISIBLE : View.INVISIBLE);
getBackButton().setVisibility(View.VISIBLE);
getHomeHandle().setVisibility(View.INVISIBLE);
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ee62dea7f9e5..6b1e918a3c47 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -149,6 +149,11 @@ public class Binder implements IBinder {
private static volatile boolean sStackTrackingEnabled = false;
/**
+ * The extension binder object
+ */
+ private IBinder mExtension = null;
+
+ /**
* Enable Binder IPC stack tracking. If enabled, every binder transaction will be logged to
* {@link TransactionTracker}.
*
@@ -1237,7 +1242,9 @@ public class Binder implements IBinder {
/** @hide */
@Override
- public final native @Nullable IBinder getExtension();
+ public final @Nullable IBinder getExtension() {
+ return mExtension;
+ }
/**
* Set the binder extension.
@@ -1245,7 +1252,12 @@ public class Binder implements IBinder {
*
* @hide
*/
- public final native void setExtension(@Nullable IBinder extension);
+ public final void setExtension(@Nullable IBinder extension) {
+ mExtension = extension;
+ setExtensionNative(extension);
+ }
+
+ private final native void setExtensionNative(@Nullable IBinder extension);
/**
* Default implementation rewinds the parcels and calls onTransact. On
diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
index 50b621c46778..1e663342522b 100644
--- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
@@ -39,7 +39,6 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.ravenwood.RavenwoodEnvironment;
import dalvik.annotation.optimization.NeverCompile;
-import dalvik.annotation.optimization.NeverInline;
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
@@ -238,7 +237,6 @@ public final class MessageQueue {
private final MatchDeliverableMessages mMatchDeliverableMessages =
new MatchDeliverableMessages();
- @NeverInline
private boolean isIdleConcurrent() {
final long now = SystemClock.uptimeMillis();
@@ -269,7 +267,6 @@ public final class MessageQueue {
return true;
}
- @NeverInline
private boolean isIdleLegacy() {
synchronized (this) {
final long now = SystemClock.uptimeMillis();
@@ -292,14 +289,12 @@ public final class MessageQueue {
}
}
- @NeverInline
private void addIdleHandlerConcurrent(@NonNull IdleHandler handler) {
synchronized (mIdleHandlersLock) {
mIdleHandlers.add(handler);
}
}
- @NeverInline
private void addIdleHandlerLegacy(@NonNull IdleHandler handler) {
synchronized (this) {
mIdleHandlers.add(handler);
@@ -326,15 +321,11 @@ public final class MessageQueue {
addIdleHandlerLegacy(handler);
}
}
-
- @NeverInline
private void removeIdleHandlerConcurrent(@NonNull IdleHandler handler) {
synchronized (mIdleHandlersLock) {
mIdleHandlers.remove(handler);
}
}
-
- @NeverInline
private void removeIdleHandlerLegacy(@NonNull IdleHandler handler) {
synchronized (this) {
mIdleHandlers.remove(handler);
@@ -358,14 +349,12 @@ public final class MessageQueue {
}
}
- @NeverInline
private boolean isPollingConcurrent() {
// If the loop is quitting then it must not be idling.
// We can assume mPtr != 0 when sQuitting is false.
return !((boolean) sQuitting.getVolatile(this)) && nativeIsPolling(mPtr);
}
- @NeverInline
private boolean isPollingLegacy() {
synchronized (this) {
return isPollingLocked();
@@ -396,7 +385,6 @@ public final class MessageQueue {
// We can assume mPtr != 0 when mQuitting is false.
return !mQuitting && nativeIsPolling(mPtr);
}
- @NeverInline
private void addOnFileDescriptorEventListenerConcurrent(@NonNull FileDescriptor fd,
@OnFileDescriptorEventListener.Events int events,
@NonNull OnFileDescriptorEventListener listener) {
@@ -405,7 +393,6 @@ public final class MessageQueue {
}
}
- @NeverInline
private void addOnFileDescriptorEventListenerLegacy(@NonNull FileDescriptor fd,
@OnFileDescriptorEventListener.Events int events,
@NonNull OnFileDescriptorEventListener listener) {
@@ -455,14 +442,12 @@ public final class MessageQueue {
}
}
- @NeverInline
private void removeOnFileDescriptorEventListenerConcurrent(@NonNull FileDescriptor fd) {
synchronized (mFileDescriptorRecordsLock) {
updateOnFileDescriptorEventListenerLocked(fd, 0, null);
}
}
- @NeverInline
private void removeOnFileDescriptorEventListenerLegacy(@NonNull FileDescriptor fd) {
synchronized (this) {
updateOnFileDescriptorEventListenerLocked(fd, 0, null);
@@ -796,7 +781,6 @@ public final class MessageQueue {
}
}
- @NeverInline
private Message nextConcurrent() {
final long ptr = mPtr;
if (ptr == 0) {
@@ -871,7 +855,6 @@ public final class MessageQueue {
}
}
- @NeverInline
private Message nextLegacy() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
@@ -1036,13 +1019,11 @@ public final class MessageQueue {
}
}
- @NeverInline
private int postSyncBarrierConcurrent() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
- @NeverInline
private int postSyncBarrierLegacy() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
@@ -1162,7 +1143,6 @@ public final class MessageQueue {
}
}
- @NeverInline
private void removeSyncBarrierConcurrent(int token) {
boolean removed;
MessageNode first;
@@ -1189,7 +1169,6 @@ public final class MessageQueue {
}
}
- @NeverInline
private void removeSyncBarrierLegacy(int token) {
synchronized (this) {
Message prev = null;
@@ -1249,7 +1228,6 @@ public final class MessageQueue {
}
- @NeverInline
private boolean enqueueMessageConcurrent(Message msg, long when) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
@@ -1258,7 +1236,6 @@ public final class MessageQueue {
return enqueueMessageUnchecked(msg, when);
}
- @NeverInline
private boolean enqueueMessageLegacy(Message msg, long when) {
synchronized (this) {
if (msg.isInUse()) {
@@ -1495,13 +1472,11 @@ public final class MessageQueue {
private final MatchHandlerWhatAndObject mMatchHandlerWhatAndObject =
new MatchHandlerWhatAndObject();
- @NeverInline
private boolean hasMessagesConcurrent(Handler h, int what, Object object) {
return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject,
false);
}
- @NeverInline
private boolean hasMessagesLegacy(Handler h, int what, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -1540,13 +1515,11 @@ public final class MessageQueue {
private final MatchHandlerWhatAndObjectEquals mMatchHandlerWhatAndObjectEquals =
new MatchHandlerWhatAndObjectEquals();
- @NeverInline
private boolean hasEqualMessagesConcurrent(Handler h, int what, Object object) {
return findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals,
false);
}
- @NeverInline
private boolean hasEqualMessagesLegacy(Handler h, int what, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -1585,13 +1558,11 @@ public final class MessageQueue {
private final MatchHandlerRunnableAndObject mMatchHandlerRunnableAndObject =
new MatchHandlerRunnableAndObject();
- @NeverInline
private boolean hasMessagesConcurrent(Handler h, Runnable r, Object object) {
return findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject,
false);
}
- @NeverInline
private boolean hasMessagesLegacy(Handler h, Runnable r, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -1626,12 +1597,10 @@ public final class MessageQueue {
}
private final MatchHandler mMatchHandler = new MatchHandler();
- @NeverInline
private boolean hasMessagesConcurrent(Handler h) {
return findOrRemoveMessages(h, -1, null, null, 0, mMatchHandler, false);
}
- @NeverInline
private boolean hasMessagesLegacy(Handler h) {
synchronized (this) {
Message p = mMessages;
@@ -1656,12 +1625,10 @@ public final class MessageQueue {
}
}
- @NeverInline
private void removeMessagesConcurrent(Handler h, int what, Object object) {
findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObject, true);
}
- @NeverInline
private void removeMessagesLegacy(Handler h, int what, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -1716,12 +1683,10 @@ public final class MessageQueue {
}
}
- @NeverInline
private void removeEqualMessagesConcurrent(Handler h, int what, Object object) {
findOrRemoveMessages(h, what, object, null, 0, mMatchHandlerWhatAndObjectEquals, true);
}
- @NeverInline
private void removeEqualMessagesLegacy(Handler h, int what, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -1777,12 +1742,10 @@ public final class MessageQueue {
}
}
- @NeverInline
private void removeMessagesConcurrent(Handler h, Runnable r, Object object) {
findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObject, true);
}
- @NeverInline
private void removeMessagesLegacy(Handler h, Runnable r, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -1852,12 +1815,10 @@ public final class MessageQueue {
private final MatchHandlerRunnableAndObjectEquals mMatchHandlerRunnableAndObjectEquals =
new MatchHandlerRunnableAndObjectEquals();
- @NeverInline
private void removeEqualMessagesConcurrent(Handler h, Runnable r, Object object) {
findOrRemoveMessages(h, -1, object, r, 0, mMatchHandlerRunnableAndObjectEquals, true);
}
- @NeverInline
private void removeEqualMessagesLegacy(Handler h, Runnable r, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -1926,12 +1887,10 @@ public final class MessageQueue {
}
private final MatchHandlerAndObject mMatchHandlerAndObject = new MatchHandlerAndObject();
- @NeverInline
private void removeCallbacksAndMessagesConcurrent(Handler h, Object object) {
findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObject, true);
}
- @NeverInline
private void removeCallbacksAndMessagesLegacy(Handler h, Object object) {
synchronized (this) {
Message p = mMessages;
@@ -2000,12 +1959,10 @@ public final class MessageQueue {
private final MatchHandlerAndObjectEquals mMatchHandlerAndObjectEquals =
new MatchHandlerAndObjectEquals();
- @NeverInline
void removeCallbacksAndEqualMessagesConcurrent(Handler h, Object object) {
findOrRemoveMessages(h, -1, object, null, 0, mMatchHandlerAndObjectEquals, true);
}
- @NeverInline
void removeCallbacksAndEqualMessagesLegacy(Handler h, Object object) {
synchronized (this) {
Message p = mMessages;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 967f55ce7a88..6c21dbf126bb 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2910,10 +2910,18 @@ public class UserManager {
* <p>Currently, on most form factors the first human user on the device will be the main user;
* in the future, the concept may be transferable, so a different user (or even no user at all)
* may be designated the main user instead. On other form factors there might not be a main
+ * user. In the future, the concept may be removed, i.e. typical future devices may have no main
* user.
*
* <p>Note that this will not be the system user on devices for which
* {@link #isHeadlessSystemUserMode()} returns true.
+ *
+ * <p>NB: Features should ideally not limit functionality to the main user. Ideally, they
+ * should either work for all users or for all admin users. If a feature should only work for
+ * select users, its determination of which user should be done intelligently or be
+ * customizable. Not all devices support a main user, and the idea of singling out one user as
+ * special is contrary to overall multiuser goals.
+ *
* @hide
*/
@SystemApi
@@ -2930,6 +2938,12 @@ public class UserManager {
/**
* Returns the designated "main user" of the device, or {@code null} if there is no main user.
*
+ * <p>NB: Features should ideally not limit functionality to the main user. Ideally, they
+ * should either work for all users or for all admin users. If a feature should only work for
+ * select users, its determination of which user should be done intelligently or be
+ * customizable. Not all devices support a main user, and the idea of singling out one user as
+ * special is contrary to overall multiuser goals.
+ *
* @see #isMainUser()
* @hide
*/
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 073f512a85fb..09ebc9f030c2 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Notification;
import android.os.Build;
import android.os.Bundle;
@@ -223,6 +224,14 @@ public final class Adjustment implements Parcelable {
public static final int TYPE_CONTENT_RECOMMENDATION = 4;
/**
+ * Data type: String, the classification type of this notification. The OS may display
+ * notifications differently depending on the type, and may change the alerting level of the
+ * notification.
+ */
+ @FlaggedApi(android.app.Flags.FLAG_NM_SUMMARIZATION)
+ public static final String KEY_SUMMARIZATION = "key_summarization";
+
+ /**
* Create a notification adjustment.
*
* @param pkg The package of the notification.
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 72569075c2ed..f23006584621 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UiThread;
import android.app.ActivityManager;
import android.app.INotificationManager;
@@ -56,6 +57,7 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.widget.RemoteViews;
@@ -1824,6 +1826,7 @@ public abstract class NotificationListenerService extends Service {
private int mProposedImportance;
// Sensitive info detected by the notification assistant
private boolean mSensitiveContent;
+ private String mSummarization;
private static final int PARCEL_VERSION = 2;
@@ -1864,6 +1867,7 @@ public abstract class NotificationListenerService extends Service {
out.writeBoolean(mIsBubble);
out.writeInt(mProposedImportance);
out.writeBoolean(mSensitiveContent);
+ out.writeString(mSummarization);
}
/** @hide */
@@ -1904,6 +1908,7 @@ public abstract class NotificationListenerService extends Service {
mIsBubble = in.readBoolean();
mProposedImportance = in.readInt();
mSensitiveContent = in.readBoolean();
+ mSummarization = in.readString();
}
@@ -2180,6 +2185,16 @@ public abstract class NotificationListenerService extends Service {
}
/**
+ * Returns a summary of the content in the notification, or potentially of the current
+ * notification and related notifications (for example, if this is provided for a group
+ * summary notification it may be summarizing all the child notifications).
+ */
+ @FlaggedApi(android.app.Flags.FLAG_NM_SUMMARIZATION)
+ public @Nullable String getSummarization() {
+ return mSummarization;
+ }
+
+ /**
* Returns the intended transition to ranking passed by {@link NotificationAssistantService}
* @hide
*/
@@ -2201,7 +2216,7 @@ public abstract class NotificationListenerService extends Service {
ArrayList<CharSequence> smartReplies, boolean canBubble,
boolean isTextChanged, boolean isConversation, ShortcutInfo shortcutInfo,
int rankingAdjustment, boolean isBubble, int proposedImportance,
- boolean sensitiveContent) {
+ boolean sensitiveContent, String summarization) {
mKey = key;
mRank = rank;
mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -2229,6 +2244,7 @@ public abstract class NotificationListenerService extends Service {
mIsBubble = isBubble;
mProposedImportance = proposedImportance;
mSensitiveContent = sensitiveContent;
+ mSummarization = TextUtils.nullIfEmpty(summarization);
}
/**
@@ -2271,7 +2287,8 @@ public abstract class NotificationListenerService extends Service {
other.mRankingAdjustment,
other.mIsBubble,
other.mProposedImportance,
- other.mSensitiveContent);
+ other.mSensitiveContent,
+ other.mSummarization);
}
/**
@@ -2332,7 +2349,8 @@ public abstract class NotificationListenerService extends Service {
&& Objects.equals(mRankingAdjustment, other.mRankingAdjustment)
&& Objects.equals(mIsBubble, other.mIsBubble)
&& Objects.equals(mProposedImportance, other.mProposedImportance)
- && Objects.equals(mSensitiveContent, other.mSensitiveContent);
+ && Objects.equals(mSensitiveContent, other.mSensitiveContent)
+ && Objects.equals(mSummarization, other.mSummarization);
}
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7c75d7b30037..0e329c2859db 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -44,7 +44,6 @@ import android.app.Activity;
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application;
-import android.app.LoadedApk;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.appwidget.AppWidgetHostView;
@@ -8484,8 +8483,14 @@ public class RemoteViews implements Parcelable, Filter {
return context;
}
try {
- LoadedApk.checkAndUpdateApkPaths(mApplication);
- Context applicationContext = context.createApplicationContext(mApplication,
+ // Use PackageManager as the source of truth for application information, rather
+ // than the parceled ApplicationInfo provided by the app.
+ ApplicationInfo sanitizedApplication =
+ context.getPackageManager().getApplicationInfoAsUser(
+ mApplication.packageName, 0,
+ UserHandle.getUserId(mApplication.uid));
+ Context applicationContext = context.createApplicationContext(
+ sanitizedApplication,
Context.CONTEXT_RESTRICTED);
// Get the correct apk paths while maintaining the current context's configuration.
return applicationContext.createConfigurationContext(
diff --git a/core/java/android/window/DesktopExperienceFlags.java b/core/java/android/window/DesktopExperienceFlags.java
new file mode 100644
index 000000000000..0d1bb77ae8a2
--- /dev/null
+++ b/core/java/android/window/DesktopExperienceFlags.java
@@ -0,0 +1,124 @@
+/*
+ * 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 android.window;
+
+import static com.android.server.display.feature.flags.Flags.enableDisplayContentModeManagement;
+
+import android.annotation.Nullable;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import com.android.window.flags.Flags;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Checks Desktop Experience flag state.
+ *
+ * <p>This enum provides a centralized way to control the behavior of flags related to desktop
+ * experience 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 the {@code
+ * persist.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.
+ *
+ * @hide
+ */
+public enum DesktopExperienceFlags {
+ ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT(() -> enableDisplayContentModeManagement(), true);
+
+ /**
+ * Flag class, to be used in case the enum cannot be used because the flag is not accessible.
+ *
+ * <p>This class will still use the process-wide cache.
+ */
+ public static class DesktopExperienceFlag {
+ // Function called to obtain aconfig flag value.
+ private final BooleanSupplier mFlagFunction;
+ // Whether the flag state should be affected by developer option.
+ private final boolean mShouldOverrideByDevOption;
+
+ public DesktopExperienceFlag(BooleanSupplier flagFunction, boolean shouldOverrideByDevOption) {
+ this.mFlagFunction = flagFunction;
+ this.mShouldOverrideByDevOption = shouldOverrideByDevOption;
+ }
+
+ /**
+ * Determines state of flag based on the actual flag and desktop experience developer option
+ * overrides.
+ */
+ public boolean isTrue() {
+ return isFlagTrue(mFlagFunction, mShouldOverrideByDevOption);
+ }
+ }
+
+ private static final String TAG = "DesktopExperienceFlags";
+ // Function called to obtain aconfig flag value.
+ private final BooleanSupplier mFlagFunction;
+ // Whether the flag state should be affected by developer option.
+ private final boolean mShouldOverrideByDevOption;
+
+ // 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;
+
+ public static final String SYSTEM_PROPERTY_NAME = "persist.wm.debug.desktop_experience_devopts";
+
+ DesktopExperienceFlags(BooleanSupplier flagFunction, boolean shouldOverrideByDevOption) {
+ this.mFlagFunction = flagFunction;
+ this.mShouldOverrideByDevOption = shouldOverrideByDevOption;
+ }
+
+ /**
+ * Determines state of flag based on the actual flag and desktop experience developer option
+ * overrides.
+ */
+ public boolean isTrue() {
+ return isFlagTrue(mFlagFunction, mShouldOverrideByDevOption);
+ }
+
+ private static boolean isFlagTrue(
+ BooleanSupplier flagFunction, boolean shouldOverrideByDevOption) {
+ if (shouldOverrideByDevOption
+ && Flags.showDesktopExperienceDevOption()
+ && getToggleOverride()) {
+ return true;
+ }
+ return flagFunction.getAsBoolean();
+ }
+
+ private static boolean getToggleOverride() {
+ // If cached, return it
+ if (sCachedToggleOverride != null) {
+ return sCachedToggleOverride;
+ }
+
+ // Otherwise, fetch and cache it
+ boolean override = getToggleOverrideFromSystem();
+ sCachedToggleOverride = override;
+ Log.d(TAG, "Toggle override initialized to: " + override);
+ return override;
+ }
+
+ /** Returns the {@link ToggleOverride} from the system property.. */
+ private static boolean getToggleOverrideFromSystem() {
+ return SystemProperties.getBoolean(SYSTEM_PROPERTY_NAME, false);
+ }
+}
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index d44b941082b5..e51ef4f6d04c 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -35,6 +35,10 @@ 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.
*
@@ -89,7 +93,8 @@ public enum DesktopModeFlags {
ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX(
Flags::enableDesktopAppLaunchTransitionsBugfix, false),
INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC(
- Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true);
+ Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true),
+ ENABLE_MINIMIZE_BUTTON(Flags::enableMinimizeButton, true);
/**
* Flag class, to be used in case the enum cannot be used because the flag is not accessible.
@@ -109,7 +114,7 @@ public enum DesktopModeFlags {
/**
* Determines state of flag based on the actual flag and desktop mode developer option
- * overrides.
+ * or desktop experience developer option overrides.
*/
public boolean isTrue() {
return isFlagTrue(mFlagFunction, mShouldOverrideByDevOption);
diff --git a/core/java/android/window/OWNERS b/core/java/android/window/OWNERS
index 77c99b98cf4a..82d37244dc70 100644
--- a/core/java/android/window/OWNERS
+++ b/core/java/android/window/OWNERS
@@ -3,3 +3,4 @@ set noparent
include /services/core/java/com/android/server/wm/OWNERS
per-file DesktopModeFlags.java = file:/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
+per-file DesktopExperienceFlags.java = file:/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 1bae15cc5077..e35c3b80a58b 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -572,4 +572,14 @@ flag {
metadata {
purpose: PURPOSE_BUGFIX
}
-} \ No newline at end of file
+}
+
+flag {
+ name: "enable_desktop_windowing_exit_by_minimize_transition_bugfix"
+ namespace: "lse_desktop_experience"
+ description: "Enables exit desktop windowing by minimize transition & motion polish changes"
+ bug: "390161102"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index ec3975205542..72cb9d1a20ac 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -51,6 +51,14 @@ oneway interface IStatusBar
void showWirelessChargingAnimation(int batteryLevel);
+ /**
+ * Sets the new IME window status.
+ *
+ * @param displayId The id of the display to which the IME is bound.
+ * @param vis The IME window visibility.
+ * @param backDisposition The IME back disposition mode.
+ * @param showImeSwitcher Whether the IME Switcher button should be shown.
+ */
void setImeWindowStatus(int displayId, int vis, int backDisposition, boolean showImeSwitcher);
void setWindowState(int display, int window, int state);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index ec0954d5590a..1fa1e0bbc69a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -61,6 +61,14 @@ interface IStatusBarService
void setIconVisibility(String slot, boolean visible);
@UnsupportedAppUsage
void removeIcon(String slot);
+ /**
+ * Sets the new IME window status.
+ *
+ * @param displayId The id of the display to which the IME is bound.
+ * @param vis The IME window visibility.
+ * @param backDisposition The IME back disposition mode.
+ * @param showImeSwitcher Whether the IME Switcher button should be shown.
+ */
void setImeWindowStatus(int displayId, int vis, int backDisposition, boolean showImeSwitcher);
void expandSettingsPanel(String subPanel);
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 639f5bff7614..91b25c2bda06 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -74,6 +74,7 @@ static struct bindernative_offsets_t
jmethodID mExecTransact;
jmethodID mGetInterfaceDescriptor;
jmethodID mTransactionCallback;
+ jmethodID mGetExtension;
// Object state.
jfieldID mObject;
@@ -489,8 +490,12 @@ public:
if (mVintf) {
::android::internal::Stability::markVintf(b.get());
}
- if (mExtension != nullptr) {
- b.get()->setExtension(mExtension);
+ if (mSetExtensionCalled) {
+ jobject javaIBinderObject = env->CallObjectMethod(obj, gBinderOffsets.mGetExtension);
+ sp<IBinder> extensionFromJava = ibinderForJavaObject(env, javaIBinderObject);
+ if (extensionFromJava != nullptr) {
+ b.get()->setExtension(extensionFromJava);
+ }
}
mBinder = b;
ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
@@ -516,21 +521,12 @@ public:
mVintf = false;
}
- sp<IBinder> getExtension() {
- AutoMutex _l(mLock);
- sp<JavaBBinder> b = mBinder.promote();
- if (b != nullptr) {
- return b.get()->getExtension();
- }
- return mExtension;
- }
-
void setExtension(const sp<IBinder>& extension) {
AutoMutex _l(mLock);
- mExtension = extension;
+ mSetExtensionCalled = true;
sp<JavaBBinder> b = mBinder.promote();
if (b != nullptr) {
- b.get()->setExtension(mExtension);
+ b.get()->setExtension(extension);
}
}
@@ -542,8 +538,7 @@ private:
// is too much binder state here, we can think about making JavaBBinder an
// sp here (avoid recreating it)
bool mVintf = false;
-
- sp<IBinder> mExtension;
+ bool mSetExtensionCalled = false;
};
// ----------------------------------------------------------------------------
@@ -1249,10 +1244,6 @@ static void android_os_Binder_blockUntilThreadAvailable(JNIEnv* env, jobject cla
return IPCThreadState::self()->blockUntilThreadAvailable();
}
-static jobject android_os_Binder_getExtension(JNIEnv* env, jobject obj) {
- JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);
- return javaObjectForIBinder(env, jbh->getExtension());
-}
static void android_os_Binder_setExtension(JNIEnv* env, jobject obj, jobject extensionObject) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);
@@ -1295,8 +1286,7 @@ static const JNINativeMethod gBinderMethods[] = {
{ "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder },
{ "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer },
{ "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable },
- { "getExtension", "()Landroid/os/IBinder;", (void*)android_os_Binder_getExtension },
- { "setExtension", "(Landroid/os/IBinder;)V", (void*)android_os_Binder_setExtension },
+ { "setExtensionNative", "(Landroid/os/IBinder;)V", (void*)android_os_Binder_setExtension },
};
// clang-format on
@@ -1313,6 +1303,8 @@ static int int_register_android_os_Binder(JNIEnv* env)
gBinderOffsets.mTransactionCallback =
GetStaticMethodIDOrDie(env, clazz, "transactionCallback", "(IIII)V");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
+ gBinderOffsets.mGetExtension = GetMethodIDOrDie(env, clazz, "getExtension",
+ "()Landroid/os/IBinder;");
return RegisterMethodsOrDie(
env, kBinderPathName,
diff --git a/core/res/res/values/public-final.xml b/core/res/res/values/public-final.xml
index d421944917ea..d8e89318a134 100644
--- a/core/res/res/values/public-final.xml
+++ b/core/res/res/values/public-final.xml
@@ -3922,4 +3922,86 @@
<public type="color" name="system_error_900" id="0x010600d0" />
<public type="color" name="system_error_1000" id="0x010600d1" />
+ <!-- ===============================================================
+ Resources added in version NEXT of the platform
+
+ NOTE: After this version of the platform is forked, changes cannot be made to the root
+ branch's groups for that release. Only merge changes to the forked platform branch.
+ =============================================================== -->
+ <eat-comment/>
+
+ <staging-public-group-final type="attr" first-id="0x01b70000">
+ <public name="removed_" />
+ <!-- @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") -->
+ <public name="adServiceTypes" />
+ <!-- @FlaggedApi("android.view.inputmethod.ime_switcher_revamp_api") -->
+ <public name="languageSettingsActivity"/>
+ <!-- @FlaggedApi(android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM) -->
+ <public name="dreamCategory"/>
+ <!-- @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled")
+ @hide @SystemApi -->
+ <public name="backgroundPermission"/>
+ <!-- @FlaggedApi(android.view.accessibility.supplemental_description) -->
+ <public name="supplementalDescription"/>
+ <!-- @FlaggedApi("android.security.enable_intent_matching_flags") -->
+ <public name="intentMatchingFlags"/>
+ <!-- @FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API) -->
+ <public name="layoutLabel"/>
+ <public name="removed_" />
+ <public name="removed_" />
+ <!-- @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) -->
+ <public name="pageSizeCompat" />
+ <!-- @FlaggedApi(android.nfc.Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES) -->
+ <public name="wantsRoleHolderPriority"/>
+ <!-- @FlaggedApi(android.sdk.Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME) -->
+ <public name="minSdkVersionFull"/>
+ <public name="removed_" />
+ <public name="removed_" />
+ <public name="removed_" />
+ <public name="removed_" />
+ </staging-public-group-final>
+
+ <!-- @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") -->
+ <public type="attr" name="adServiceTypes" id="0x010106a4" />
+ <!-- @FlaggedApi("android.view.inputmethod.ime_switcher_revamp_api") -->
+ <public type="attr" name="languageSettingsActivity" id="0x010106a5" />
+ <!-- @FlaggedApi(android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM) -->
+ <public type="attr" name="dreamCategory" id="0x010106a6" />
+ <!-- @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled")
+ @hide @SystemApi -->
+ <public type="attr" name="backgroundPermission" id="0x010106a7" />
+ <!-- @FlaggedApi(android.view.accessibility.supplemental_description) -->
+ <public type="attr" name="supplementalDescription" id="0x010106a8" />
+ <!-- @FlaggedApi("android.security.enable_intent_matching_flags") -->
+ <public type="attr" name="intentMatchingFlags" id="0x010106a9" />
+ <!-- @FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API) -->
+ <public type="attr" name="layoutLabel" id="0x010106aa" />
+ <!-- @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) -->
+ <public type="attr" name="pageSizeCompat" id="0x010106ab" />
+ <!-- @FlaggedApi(android.nfc.Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES) -->
+ <public type="attr" name="wantsRoleHolderPriority" id="0x010106ac" />
+ <!-- @FlaggedApi(android.sdk.Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME) -->
+ <public type="attr" name="minSdkVersionFull" id="0x010106ad" />
+
+ <staging-public-group-final type="string" first-id="0x01b40000">
+ <!-- @FlaggedApi(android.content.pm.Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
+ @hide @SystemApi -->
+ <public name="config_systemDependencyInstaller" />
+ <!-- @hide @SystemApi -->
+ <public name="removed_config_defaultReservedForTestingProfileGroupExclusivity" />
+ <!-- @FlaggedApi(android.permission.flags.Flags.FLAG_SYSTEM_VENDOR_INTELLIGENCE_ROLE_ENABLED)
+ @hide @SystemApi -->
+ <public name="config_systemVendorIntelligence" />
+ <public name="removed_" />
+ <public name="removed_" />
+ <public name="removed_" />
+ </staging-public-group-final>
+
+ <!-- @FlaggedApi(android.content.pm.Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
+ @hide @SystemApi -->
+ <public type="string" name="config_systemDependencyInstaller" id="0x0104004a" />
+ <!-- @FlaggedApi(android.permission.flags.Flags.FLAG_SYSTEM_VENDOR_INTELLIGENCE_ROLE_ENABLED)
+ @hide @SystemApi -->
+ <public type="string" name="config_systemVendorIntelligence" id="0x0104004b" />
+
</resources>
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index a0c4c13a8702..2d411d0268b3 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -109,34 +109,13 @@
=============================================================== -->
<eat-comment/>
- <staging-public-group type="attr" first-id="0x01b70000">
+ <staging-public-group type="attr" first-id="0x01b30000">
<!-- @FlaggedApi("android.content.pm.sdk_lib_independence") -->
<public name="optional"/>
- <!-- @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") -->
- <public name="adServiceTypes" />
- <!-- @FlaggedApi("android.view.inputmethod.ime_switcher_revamp_api") -->
- <public name="languageSettingsActivity"/>
- <!-- @FlaggedApi(android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM) -->
- <public name="dreamCategory"/>
- <!-- @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled")
- @hide @SystemApi -->
- <public name="backgroundPermission"/>
- <!-- @FlaggedApi(android.view.accessibility.supplemental_description) -->
- <public name="supplementalDescription"/>
- <!-- @FlaggedApi("android.security.enable_intent_matching_flags") -->
- <public name="intentMatchingFlags"/>
- <!-- @FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API) -->
- <public name="layoutLabel"/>
<!-- @FlaggedApi(android.content.pm.Flags.FLAG_CHANGE_LAUNCHER_BADGING) -->
<public name="alternateLauncherIcons"/>
<!-- @FlaggedApi(android.content.pm.Flags.FLAG_CHANGE_LAUNCHER_BADGING) -->
<public name="alternateLauncherLabels"/>
- <!-- @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) -->
- <public name="pageSizeCompat" />
- <!-- @FlaggedApi(android.nfc.Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES) -->
- <public name="wantsRoleHolderPriority"/>
- <!-- @FlaggedApi(android.sdk.Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME) -->
- <public name="minSdkVersionFull"/>
<!-- @hide Only for device overlay to use this. -->
<public name="pointerIconVectorFill"/>
<!-- @hide Only for device overlay to use this. -->
@@ -147,39 +126,27 @@
<public name="pointerIconVectorStrokeInverse"/>
</staging-public-group>
- <staging-public-group type="id" first-id="0x01b60000">
+ <staging-public-group type="id" first-id="0x01b20000">
<!-- @FlaggedApi(android.appwidget.flags.Flags.FLAG_ENGAGEMENT_METRICS) -->
<public name="remoteViewsMetricsId"/>
</staging-public-group>
- <staging-public-group type="style" first-id="0x01b50000">
+ <staging-public-group type="style" first-id="0x01b10000">
</staging-public-group>
- <staging-public-group type="string" first-id="0x01b40000">
- <!-- @FlaggedApi(android.content.pm.Flags.FLAG_SDK_DEPENDENCY_INSTALLER)
- @hide @SystemApi -->
- <public name="config_systemDependencyInstaller" />
- <!-- @hide @SystemApi -->
- <public name="removed_config_defaultReservedForTestingProfileGroupExclusivity" />
- <!-- @FlaggedApi(android.permission.flags.Flags.FLAG_SYSTEM_VENDOR_INTELLIGENCE_ROLE_ENABLED)
- @hide @SystemApi -->
- <public name="config_systemVendorIntelligence" />
-
+ <staging-public-group type="string" first-id="0x01b00000">
<!-- @FlaggedApi(android.app.ondeviceintelligence.flags.Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE_MODULE)
@hide @SystemApi -->
<public name="config_defaultOnDeviceIntelligenceService" />
-
<!-- @FlaggedApi(android.app.ondeviceintelligence.flags.Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE_MODULE)
@hide @SystemApi -->
<public name="config_defaultOnDeviceSandboxedInferenceService" />
-
<!-- @FlaggedApi(android.app.ondeviceintelligence.flags.Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE_MODULE)
@hide @SystemApi -->
<public name="config_defaultOnDeviceIntelligenceDeviceConfigNamespace" />
-
</staging-public-group>
- <staging-public-group type="dimen" first-id="0x01b30000">
+ <staging-public-group type="dimen" first-id="0x01af0000">
<!-- @FlaggedApi(android.os.Flags.FLAG_MATERIAL_MOTION_TOKENS)-->
<public name="config_motionStandardFastSpatialDamping"/>
<!-- @FlaggedApi(android.os.Flags.FLAG_MATERIAL_MOTION_TOKENS)-->
@@ -216,7 +183,7 @@
<public name="config_shapeCornerRadiusXlarge"/>
</staging-public-group>
- <staging-public-group type="color" first-id="0x01b20000">
+ <staging-public-group type="color" first-id="0x01ae0000">
<!-- @FlaggedApi(android.os.Flags.FLAG_MATERIAL_COLORS_10_2024)-->
<public name="system_inverse_on_surface_light"/>
<!-- @FlaggedApi(android.os.Flags.FLAG_MATERIAL_COLORS_10_2024)-->
@@ -243,28 +210,28 @@
<public name="system_surface_tint_dark"/>
</staging-public-group>
- <staging-public-group type="array" first-id="0x01b10000">
+ <staging-public-group type="array" first-id="0x01ad0000">
</staging-public-group>
- <staging-public-group type="drawable" first-id="0x01b00000">
+ <staging-public-group type="drawable" first-id="0x01ac0000">
</staging-public-group>
- <staging-public-group type="layout" first-id="0x01af0000">
+ <staging-public-group type="layout" first-id="0x01ab0000">
</staging-public-group>
- <staging-public-group type="anim" first-id="0x01ae0000">
+ <staging-public-group type="anim" first-id="0x01aa0000">
</staging-public-group>
- <staging-public-group type="animator" first-id="0x01ad0000">
+ <staging-public-group type="animator" first-id="0x01a90000">
</staging-public-group>
- <staging-public-group type="interpolator" first-id="0x01ac0000">
+ <staging-public-group type="interpolator" first-id="0x01a80000">
</staging-public-group>
- <staging-public-group type="mipmap" first-id="0x01ab0000">
+ <staging-public-group type="mipmap" first-id="0x01a70000">
</staging-public-group>
- <staging-public-group type="integer" first-id="0x01aa0000">
+ <staging-public-group type="integer" first-id="0x01a60000">
<!-- @FlaggedApi(android.os.Flags.FLAG_MATERIAL_MOTION_TOKENS)-->
<public name="config_motionStandardFastSpatialStiffness"/>
<!-- @FlaggedApi(android.os.Flags.FLAG_MATERIAL_MOTION_TOKENS)-->
@@ -291,16 +258,16 @@
<public name="config_motionExpressiveSlowEffectStiffness"/>
</staging-public-group>
- <staging-public-group type="transition" first-id="0x01a90000">
+ <staging-public-group type="transition" first-id="0x01a50000">
</staging-public-group>
- <staging-public-group type="raw" first-id="0x01a80000">
+ <staging-public-group type="raw" first-id="0x01a40000">
</staging-public-group>
- <staging-public-group type="bool" first-id="0x01a70000">
+ <staging-public-group type="bool" first-id="0x01a30000">
</staging-public-group>
- <staging-public-group type="fraction" first-id="0x01a60000">
+ <staging-public-group type="fraction" first-id="0x01a20000">
</staging-public-group>
</resources>
diff --git a/core/tests/FileSystemUtilsTest/Android.bp b/core/tests/FileSystemUtilsTest/Android.bp
index 962ff3c0a6e0..bb0acc679dc1 100644
--- a/core/tests/FileSystemUtilsTest/Android.bp
+++ b/core/tests/FileSystemUtilsTest/Android.bp
@@ -52,6 +52,36 @@ android_test_helper_app {
}
android_test_helper_app {
+ name: "app_with_4kb_compressed_elf",
+ srcs: ["app_with_4kb_elf/src/**/*.java"],
+ manifest: "app_with_4kb_elf/app_with_4kb_elf.xml",
+ compile_multilib: "64",
+ jni_libs: [
+ "libpunchtest_4kb",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "platform-test-annotations",
+ ],
+ use_embedded_native_libs: false,
+}
+
+android_test_helper_app {
+ name: "page_size_compat_disabled_app",
+ srcs: ["app_with_4kb_elf/src/**/*.java"],
+ manifest: "app_with_4kb_elf/page_size_compat_disabled.xml",
+ compile_multilib: "64",
+ jni_libs: [
+ "libpunchtest_4kb",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "platform-test-annotations",
+ ],
+ use_embedded_native_libs: true,
+}
+
+android_test_helper_app {
name: "embedded_native_libs_test_app",
srcs: ["apk_embedded_native_libs/src/**/*.java"],
manifest: "apk_embedded_native_libs/embedded_native_libs_test_app.xml",
@@ -99,6 +129,8 @@ java_test_host {
":embedded_native_libs_test_app",
":extract_native_libs_test_app",
":app_with_4kb_elf",
+ ":page_size_compat_disabled_app",
+ ":app_with_4kb_compressed_elf",
],
test_suites: ["general-tests"],
test_config: "AndroidTest.xml",
diff --git a/core/tests/FileSystemUtilsTest/AndroidTest.xml b/core/tests/FileSystemUtilsTest/AndroidTest.xml
index 651a7ca15dac..27f49b2289ba 100644
--- a/core/tests/FileSystemUtilsTest/AndroidTest.xml
+++ b/core/tests/FileSystemUtilsTest/AndroidTest.xml
@@ -22,7 +22,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="embedded_native_libs_test_app.apk" />
<option name="test-file-name" value="extract_native_libs_test_app.apk" />
- <option name="test-file-name" value="app_with_4kb_elf.apk" />
</target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
diff --git a/core/tests/FileSystemUtilsTest/app_with_4kb_elf/app_with_4kb_elf.xml b/core/tests/FileSystemUtilsTest/app_with_4kb_elf/app_with_4kb_elf.xml
index b9d6d4db2c81..d7a37336cbc3 100644
--- a/core/tests/FileSystemUtilsTest/app_with_4kb_elf/app_with_4kb_elf.xml
+++ b/core/tests/FileSystemUtilsTest/app_with_4kb_elf/app_with_4kb_elf.xml
@@ -18,7 +18,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.test.pagesizecompat">
<application
- android:extractNativeLibs="false"
android:pageSizeCompat="enabled">
<uses-library android:name="android.test.runner"/>
<activity android:name=".MainActivity"
diff --git a/core/tests/FileSystemUtilsTest/app_with_4kb_elf/page_size_compat_disabled.xml b/core/tests/FileSystemUtilsTest/app_with_4kb_elf/page_size_compat_disabled.xml
new file mode 100644
index 000000000000..641c5e741014
--- /dev/null
+++ b/core/tests/FileSystemUtilsTest/app_with_4kb_elf/page_size_compat_disabled.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.test.pagesizecompat">
+ <application
+ android:pageSizeCompat="disabled">
+ <uses-library android:name="android.test.runner"/>
+ <activity android:name=".MainActivity"
+ android:exported="true"
+ android:process=":NewProcess">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.test.pagesizecompat"/>
+</manifest> \ No newline at end of file
diff --git a/core/tests/FileSystemUtilsTest/app_with_4kb_elf/src/android/test/pagesizecompat/PageSizeCompatTest.java b/core/tests/FileSystemUtilsTest/app_with_4kb_elf/src/android/test/pagesizecompat/PageSizeCompatTest.java
index 9cbe414a0993..b4a801a09ed0 100644
--- a/core/tests/FileSystemUtilsTest/app_with_4kb_elf/src/android/test/pagesizecompat/PageSizeCompatTest.java
+++ b/core/tests/FileSystemUtilsTest/app_with_4kb_elf/src/android/test/pagesizecompat/PageSizeCompatTest.java
@@ -34,8 +34,7 @@ import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class PageSizeCompatTest {
- @Test
- public void testPageSizeCompat_embedded4KbLib() throws Exception {
+ public void testPageSizeCompat_appLaunch(boolean shouldPass) throws Exception {
Context context = InstrumentationRegistry.getContext();
CountDownLatch receivedSignal = new CountDownLatch(1);
@@ -62,6 +61,16 @@ public class PageSizeCompatTest {
launchIntent.putExtra(MainActivity.KEY_OPERAND_2, op2);
context.startActivity(launchIntent);
- Assert.assertTrue("Failed to launch app", receivedSignal.await(10, TimeUnit.SECONDS));
+ Assert.assertEquals(receivedSignal.await(10, TimeUnit.SECONDS), shouldPass);
+ }
+
+ @Test
+ public void testPageSizeCompat_compatEnabled() throws Exception {
+ testPageSizeCompat_appLaunch(true);
+ }
+
+ @Test
+ public void testPageSizeCompat_compatDisabled() throws Exception {
+ testPageSizeCompat_appLaunch(false);
}
}
diff --git a/core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java b/core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java
index aed907a0242f..6430813b9913 100644
--- a/core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java
+++ b/core/tests/FileSystemUtilsTest/src/com/android/internal/content/FileSystemUtilsTest.java
@@ -17,10 +17,12 @@
package com.android.internal.content;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AppModeFull;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -29,6 +31,10 @@ import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
public class FileSystemUtilsTest extends BaseHostJUnit4Test {
+ private static final String PAGE_SIZE_COMPAT_ENABLED = "app_with_4kb_elf.apk";
+ private static final String PAGE_SIZE_COMPAT_DISABLED = "page_size_compat_disabled_app.apk";
+ private static final String PAGE_SIZE_COMPAT_ENABLED_COMPRESSED_ELF =
+ "app_with_4kb_compressed_elf.apk";
@Test
@AppModeFull
@@ -48,12 +54,41 @@ public class FileSystemUtilsTest extends BaseHostJUnit4Test {
runDeviceTests(appPackage, appPackage + "." + testName);
}
- @Test
- @AppModeFull
- public void runAppWith4KbLib_overrideCompatMode() throws DeviceNotAvailableException {
+ private void runPageSizeCompatTest(String appName, String testMethodName)
+ throws DeviceNotAvailableException, TargetSetupError {
+ getDevice().enableAdbRoot();
+ String result = getDevice().executeShellCommand("getconf PAGE_SIZE");
+ assumeTrue("16384".equals(result.strip()));
+ installPackage(appName, "-r");
String appPackage = "android.test.pagesizecompat";
String testName = "PageSizeCompatTest";
assertTrue(isPackageInstalled(appPackage));
- runDeviceTests(appPackage, appPackage + "." + testName);
+ assertTrue(runDeviceTests(appPackage, appPackage + "." + testName,
+ testMethodName));
+ uninstallPackage(appPackage);
+ }
+
+ @Test
+ @AppModeFull
+ public void runAppWith4KbLib_overrideCompatMode()
+ throws DeviceNotAvailableException, TargetSetupError {
+ runPageSizeCompatTest(PAGE_SIZE_COMPAT_ENABLED, "testPageSizeCompat_compatEnabled");
+ }
+
+ @Test
+ @AppModeFull
+ public void runAppWith4KbCompressedLib_overrideCompatMode()
+ throws DeviceNotAvailableException, TargetSetupError {
+ runPageSizeCompatTest(PAGE_SIZE_COMPAT_ENABLED_COMPRESSED_ELF,
+ "testPageSizeCompat_compatEnabled");
+ }
+
+ @Test
+ @AppModeFull
+ public void runAppWith4KbLib_disabledCompatMode()
+ throws DeviceNotAvailableException, TargetSetupError {
+ // This test is expected to fail since compat is disabled in manifest
+ runPageSizeCompatTest(PAGE_SIZE_COMPAT_DISABLED,
+ "testPageSizeCompat_compatDisabled");
}
}
diff --git a/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java b/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java
index 1bdb006c3465..9f1580cb8b57 100644
--- a/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java
+++ b/core/tests/coretests/src/android/service/notification/NotificationRankingUpdateTest.java
@@ -124,7 +124,8 @@ public class NotificationRankingUpdateTest {
getRankingAdjustment(i),
isBubble(i),
getProposedImportance(i),
- hasSensitiveContent(i)
+ hasSensitiveContent(i),
+ getSummarization(i)
);
rankings[i] = ranking;
}
@@ -334,6 +335,17 @@ public class NotificationRankingUpdateTest {
}
/**
+ * Produces a String that can be used to represent getSummarization, based on the provided
+ * index.
+ */
+ public static String getSummarization(int index) {
+ if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization())) {
+ return "summary " + index;
+ }
+ return null;
+ }
+
+ /**
* Produces a boolean that can be used to represent isBubble, based on the provided index.
*/
public static boolean isBubble(int index) {
@@ -461,7 +473,8 @@ public class NotificationRankingUpdateTest {
/* rankingAdjustment= */ 0,
/* isBubble= */ false,
/* proposedImportance= */ 0,
- /* sensitiveContent= */ false
+ /* sensitiveContent= */ false,
+ /* summarization = */ null
);
return ranking;
}
@@ -550,7 +563,8 @@ public class NotificationRankingUpdateTest {
tweak.getRankingAdjustment(),
tweak.isBubble(),
tweak.getProposedImportance(),
- tweak.hasSensitiveContent()
+ tweak.hasSensitiveContent(),
+ tweak.getSummarization()
);
assertNotEquals(nru, nru2);
}
diff --git a/core/tests/coretests/src/android/window/DesktopExperienceFlagsTest.java b/core/tests/coretests/src/android/window/DesktopExperienceFlagsTest.java
new file mode 100644
index 000000000000..cc06f3d21332
--- /dev/null
+++ b/core/tests/coretests/src/android/window/DesktopExperienceFlagsTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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 android.window;
+
+import static com.android.window.flags.Flags.FLAG_SHOW_DESKTOP_EXPERIENCE_DEV_OPTION;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+import static org.junit.Assume.assumeFalse;
+
+import android.content.Context;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.FlagsParameterization;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.support.test.uiautomator.UiDevice;
+import android.window.DesktopExperienceFlags.DesktopExperienceFlag;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.window.flags.Flags;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * Test class for {@link android.window.DesktopExperienceFlags}
+ *
+ * <p>Build/Install/Run: atest FrameworksCoreTests:DesktopExperienceFlagsTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(ParameterizedAndroidJunit4.class)
+public class DesktopExperienceFlagsTest {
+
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getParams() {
+ return FlagsParameterization.allCombinationsOf(FLAG_SHOW_DESKTOP_EXPERIENCE_DEV_OPTION);
+ }
+
+ @Rule public SetFlagsRule mSetFlagsRule;
+
+ private UiDevice mUiDevice;
+ private Context mContext;
+ private boolean mLocalFlagValue = false;
+ private final DesktopExperienceFlag mOverriddenLocalFlag =
+ new DesktopExperienceFlag(() -> mLocalFlagValue, true);
+ private final DesktopExperienceFlag mNotOverriddenLocalFlag =
+ new DesktopExperienceFlag(() -> mLocalFlagValue, false);
+
+ private static final String OVERRIDE_OFF_SETTING = "0";
+ private static final String OVERRIDE_ON_SETTING = "1";
+ private static final String OVERRIDE_INVALID_SETTING = "garbage";
+
+ public DesktopExperienceFlagsTest(FlagsParameterization flags) {
+ mSetFlagsRule = new SetFlagsRule(flags);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ setSysProp(null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ resetCache();
+ setSysProp(null);
+ }
+
+ @Test
+ public void isTrue_overrideOff_featureFlagOn_returnsTrue() throws Exception {
+ mLocalFlagValue = true;
+ setSysProp(OVERRIDE_OFF_SETTING);
+
+ assertThat(mOverriddenLocalFlag.isTrue()).isTrue();
+ assertThat(mNotOverriddenLocalFlag.isTrue()).isTrue();
+ }
+
+ @Test
+ public void isTrue_overrideOn_featureFlagOn_returnsTrue() throws Exception {
+ mLocalFlagValue = true;
+ setSysProp(OVERRIDE_ON_SETTING);
+
+ assertThat(mOverriddenLocalFlag.isTrue()).isTrue();
+ assertThat(mNotOverriddenLocalFlag.isTrue()).isTrue();
+ }
+
+ @Test
+ public void isTrue_overrideOff_featureFlagOff_returnsFalse() throws Exception {
+ mLocalFlagValue = false;
+ setSysProp(OVERRIDE_OFF_SETTING);
+
+ assertThat(mOverriddenLocalFlag.isTrue()).isFalse();
+ assertThat(mNotOverriddenLocalFlag.isTrue()).isFalse();
+ }
+
+ @Test
+ public void isTrue_devOptionEnabled_overrideOn_featureFlagOff() throws Exception {
+ assumeTrue(Flags.showDesktopExperienceDevOption());
+ mLocalFlagValue = false;
+ setSysProp(OVERRIDE_ON_SETTING);
+
+ assertThat(mOverriddenLocalFlag.isTrue()).isTrue();
+ assertThat(mNotOverriddenLocalFlag.isTrue()).isFalse();
+ }
+
+ @Test
+ public void isTrue_devOptionDisabled_overrideOn_featureFlagOff_returnsFalse() throws Exception {
+ assumeFalse(Flags.showDesktopExperienceDevOption());
+ mLocalFlagValue = false;
+ setSysProp(OVERRIDE_ON_SETTING);
+
+ assertThat(mOverriddenLocalFlag.isTrue()).isFalse();
+ assertThat(mNotOverriddenLocalFlag.isTrue()).isFalse();
+ }
+
+ private void setSysProp(String value) throws Exception {
+ if (value == null) {
+ resetSysProp();
+ } else {
+ mUiDevice.executeShellCommand(
+ "setprop " + DesktopModeFlags.SYSTEM_PROPERTY_NAME + " " + value);
+ }
+ }
+
+ private void resetSysProp() throws Exception {
+ mUiDevice.executeShellCommand("setprop " + DesktopModeFlags.SYSTEM_PROPERTY_NAME + " ''");
+ }
+
+ private void resetCache() throws Exception {
+ Field cachedToggleOverride =
+ DesktopExperienceFlags.class.getDeclaredField("sCachedToggleOverride");
+ cachedToggleOverride.setAccessible(true);
+ cachedToggleOverride.set(null, null);
+ }
+}
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt
index dd387b382dc6..09a93d501f8e 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt
@@ -296,5 +296,9 @@ class BubbleControllerBubbleBarTest {
override fun onBubbleStateChange(update: BubbleBarUpdate?) {}
override fun animateBubbleBarLocation(location: BubbleBarLocation?) {}
+
+ override fun onDragItemOverBubbleBarDragZone(location: BubbleBarLocation) {}
+
+ override fun onItemDraggedOutsideBubbleBarDropZone() {}
}
}
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index c38d459f64d3..59e6c7786cb8 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -188,7 +188,4 @@
<string-array name="desktop_windowing_app_handle_education_allowlist_apps"></string-array>
<!-- Apps that can trigger Desktop Windowing App-To-Web Education -->
<string-array name="desktop_windowing_app_to_web_education_allowlist_apps"></string-array>
-
- <!-- Whether this device allows to drag windows across displays. -->
- <bool name="config_enableConnectedDisplayWindowDrag">true</bool>
</resources>
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java
index 2ca011bfe000..0a1e3b9495a0 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java
@@ -111,7 +111,7 @@ public class GroupedTaskInfo implements Parcelable {
* Create new for a pair of tasks in split screen
*/
public static GroupedTaskInfo forSplitTasks(@NonNull TaskInfo task1,
- @NonNull TaskInfo task2, @Nullable SplitBounds splitBounds) {
+ @NonNull TaskInfo task2, @NonNull SplitBounds splitBounds) {
return new GroupedTaskInfo(List.of(task1, task2), splitBounds, TYPE_SPLIT,
null /* minimizedFreeformTasks */);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/DesktopModeCompatPolicy.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
index e55af112cd5f..0ea3c2a80fb4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/DesktopModeCompatPolicy.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
@@ -14,20 +14,18 @@
* limitations under the License.
*/
-package com.android.wm.shell.compatui
+package com.android.wm.shell.shared.desktopmode
-import android.app.ActivityManager.RunningTaskInfo
+import android.app.TaskInfo
import android.content.Context
+import android.window.DesktopModeFlags
import com.android.internal.R
-import com.android.wm.shell.dagger.WMSingleton
-import javax.inject.Inject
/**
* Class to decide whether to apply app compat policies in desktop mode.
*/
// TODO(b/347289970): Consider replacing with API
-@WMSingleton
-class DesktopModeCompatPolicy @Inject constructor(context: Context) {
+class DesktopModeCompatPolicy(context: Context) {
private val systemUiPackage: String = context.resources.getString(R.string.config_systemUi)
@@ -37,16 +35,26 @@ class DesktopModeCompatPolicy @Inject constructor(context: Context) {
* not being displayed, regardless of its configuration, we will not exempt it as to remain in
* the desktop windowing environment.
*/
- fun isTopActivityExemptFromDesktopWindowing(task: RunningTaskInfo) =
- (isSystemUiTask(task) || isTransparentTask(task)) && !task.isTopActivityNoDisplay
+ fun isTopActivityExemptFromDesktopWindowing(task: TaskInfo) =
+ isTopActivityExemptFromDesktopWindowing(task.baseActivity?.packageName,
+ task.numActivities, task.isTopActivityNoDisplay, task.isActivityStackTransparent)
+
+ fun isTopActivityExemptFromDesktopWindowing(packageName: String?,
+ numActivities: Int, isTopActivityNoDisplay: Boolean, isActivityStackTransparent: Boolean) =
+ DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue
+ && ((isSystemUiTask(packageName)
+ || isTransparentTask(isActivityStackTransparent, numActivities))
+ && !isTopActivityNoDisplay)
/**
* Returns true if all activities in a tasks stack are transparent. If there are no activities
* will return false.
*/
- fun isTransparentTask(task: RunningTaskInfo): Boolean = task.isActivityStackTransparent
- && task.numActivities > 0
+ fun isTransparentTask(task: TaskInfo): Boolean =
+ isTransparentTask(task.isActivityStackTransparent, task.numActivities)
+
+ private fun isTransparentTask(isActivityStackTransparent: Boolean, numActivities: Int) =
+ isActivityStackTransparent && numActivities > 0
- private fun isSystemUiTask(task: RunningTaskInfo): Boolean =
- task.baseActivity?.packageName == systemUiPackage
+ private fun isSystemUiTask(packageName: String?) = packageName == systemUiPackage
}
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 e68a98fb7f21..a65e69eee5fe 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
@@ -542,7 +542,7 @@ public class Bubble implements BubbleViewProvider {
return (mMetadataShortcutId != null && !mMetadataShortcutId.isEmpty());
}
- BubbleTransitions.BubbleTransition getPreparingTransition() {
+ public BubbleTransitions.BubbleTransition getPreparingTransition() {
return mPreparingTransition;
}
@@ -572,7 +572,8 @@ public class Bubble implements BubbleViewProvider {
mIntentActive = false;
}
- private void cleanupTaskView() {
+ /** Cleans-up the taskview associated with this bubble (possibly removing the task from wm) */
+ public void cleanupTaskView() {
if (mBubbleTaskView != null) {
mBubbleTaskView.cleanup();
mBubbleTaskView = null;
@@ -593,7 +594,7 @@ public class Bubble implements BubbleViewProvider {
* <p>If we're switching between bar and floating modes, pass {@code false} on
* {@code cleanupTaskView} to avoid recreating it in the new mode.
*/
- void cleanupViews(boolean cleanupTaskView) {
+ public void cleanupViews(boolean cleanupTaskView) {
cleanupExpandedView(cleanupTaskView);
mIconView = null;
}
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 d0f912ac2142..5f2b95f7b137 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
@@ -40,9 +40,11 @@ import android.annotation.BinderThread;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.PendingIntent;
+import android.app.TaskInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -78,6 +80,8 @@ import android.view.WindowInsets;
import android.view.WindowManager;
import android.window.ScreenCapture;
import android.window.ScreenCapture.SynchronousScreenCaptureListener;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
@@ -360,7 +364,7 @@ public class BubbleController implements ConfigurationChangeListener,
} else {
tvTransitions = taskViewTransitions;
}
- mTaskViewController = tvTransitions;
+ mTaskViewController = new BubbleTaskViewController(tvTransitions);
mBubbleTransitions = new BubbleTransitions(transitions, organizer, taskViewRepository, data,
tvTransitions, context);
mTransitions = transitions;
@@ -2076,7 +2080,12 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
public void removeBubble(Bubble removedBubble) {
if (mLayerView != null) {
+ final BubbleTransitions.BubbleTransition bubbleTransit =
+ removedBubble.getPreparingTransition();
mLayerView.removeBubble(removedBubble, () -> {
+ if (bubbleTransit != null) {
+ bubbleTransit.continueCollapse();
+ }
if (!mBubbleData.hasBubbles() && !isStackExpanded()) {
mLayerView.setVisibility(INVISIBLE);
removeFromWindowManagerMaybe();
@@ -2639,6 +2648,17 @@ public class BubbleController implements ConfigurationChangeListener,
public void animateBubbleBarLocation(BubbleBarLocation location) {
mListener.call(l -> l.animateBubbleBarLocation(location));
}
+
+ @Override
+ public void onDragItemOverBubbleBarDragZone(
+ @NonNull BubbleBarLocation location) {
+ mListener.call(l -> l.onDragItemOverBubbleBarDragZone(location));
+ }
+
+ @Override
+ public void onItemDraggedOutsideBubbleBarDropZone() {
+ mListener.call(IBubblesListener::onItemDraggedOutsideBubbleBarDropZone);
+ }
};
IBubblesImpl(BubbleController controller) {
@@ -2691,7 +2711,18 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
public void collapseBubbles() {
- mMainExecutor.execute(() -> mController.collapseStack());
+ mMainExecutor.execute(() -> {
+ if (mBubbleData.getSelectedBubble() instanceof Bubble) {
+ if (((Bubble) mBubbleData.getSelectedBubble()).getPreparingTransition()
+ != null) {
+ // Currently preparing a transition which will, itself, collapse the bubble.
+ // For transition preparation, the timing of bubble-collapse must be in
+ // sync with the rest of the set-up.
+ return;
+ }
+ }
+ mController.collapseStack();
+ });
}
@Override
@@ -3083,4 +3114,84 @@ public class BubbleController implements ConfigurationChangeListener,
return mKeyToShownInShadeMap.get(key);
}
}
+
+ private class BubbleTaskViewController implements TaskViewController {
+ private final TaskViewTransitions mBaseTransitions;
+
+ BubbleTaskViewController(TaskViewTransitions baseTransitions) {
+ mBaseTransitions = baseTransitions;
+ }
+
+ @Override
+ public void registerTaskView(TaskViewTaskController tv) {
+ mBaseTransitions.registerTaskView(tv);
+ }
+
+ @Override
+ public void unregisterTaskView(TaskViewTaskController tv) {
+ mBaseTransitions.unregisterTaskView(tv);
+ }
+
+ @Override
+ public void startShortcutActivity(@NonNull TaskViewTaskController destination,
+ @NonNull ShortcutInfo shortcut, @NonNull ActivityOptions options,
+ @Nullable Rect launchBounds) {
+ mBaseTransitions.startShortcutActivity(destination, shortcut, options, launchBounds);
+ }
+
+ @Override
+ public void startActivity(@NonNull TaskViewTaskController destination,
+ @NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
+ @NonNull ActivityOptions options, @Nullable Rect launchBounds) {
+ mBaseTransitions.startActivity(destination, pendingIntent, fillInIntent,
+ options, launchBounds);
+ }
+
+ @Override
+ public void startRootTask(@NonNull TaskViewTaskController destination,
+ ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
+ @Nullable WindowContainerTransaction wct) {
+ mBaseTransitions.startRootTask(destination, taskInfo, leash, wct);
+ }
+
+ @Override
+ public void removeTaskView(@NonNull TaskViewTaskController taskView,
+ @Nullable WindowContainerToken taskToken) {
+ mBaseTransitions.removeTaskView(taskView, taskToken);
+ }
+
+ @Override
+ public void moveTaskViewToFullscreen(@NonNull TaskViewTaskController taskView) {
+ final TaskInfo tinfo = taskView.getTaskInfo();
+ if (tinfo == null) {
+ return;
+ }
+ Bubble bub = null;
+ for (Bubble b : mBubbleData.getBubbles()) {
+ if (b.getTaskId() == tinfo.taskId) {
+ bub = b;
+ break;
+ }
+ }
+ if (bub == null) {
+ return;
+ }
+ mBubbleTransitions.startConvertFromBubble(bub, tinfo);
+ }
+
+ @Override
+ public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
+ mBaseTransitions.setTaskViewVisible(taskView, visible);
+ }
+
+ @Override
+ public void setTaskBounds(TaskViewTaskController taskView, Rect boundsOnScreen) {
+ mBaseTransitions.setTaskBounds(taskView, boundsOnScreen);
+ }
+
+ @Override
+ public boolean isUsingShellTransitions() {
+ return mBaseTransitions.isUsingShellTransitions();
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 1a61793eab87..a725e04d3f8a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -87,6 +87,7 @@ public class BubblePositioner {
private int mExpandedViewLargeScreenWidth;
private int mExpandedViewLargeScreenInsetClosestEdge;
private int mExpandedViewLargeScreenInsetFurthestEdge;
+ private int mExpandedViewBubbleBarWidth;
private int mOverflowWidth;
private int mExpandedViewPadding;
@@ -158,12 +159,13 @@ public class BubblePositioner {
mBubbleOffscreenAmount = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
+ mExpandedViewBubbleBarWidth = Math.min(
+ res.getDimensionPixelSize(R.dimen.bubble_bar_expanded_view_width),
+ mPositionRect.width() - 2 * mExpandedViewPadding
+ );
if (mShowingInBubbleBar) {
- mExpandedViewLargeScreenWidth = Math.min(
- res.getDimensionPixelSize(R.dimen.bubble_bar_expanded_view_width),
- mPositionRect.width() - 2 * mExpandedViewPadding
- );
+ mExpandedViewLargeScreenWidth = mExpandedViewBubbleBarWidth;
} else if (mDeviceConfig.isSmallTablet()) {
mExpandedViewLargeScreenWidth = (int) (bounds.width()
* EXPANDED_VIEW_SMALL_TABLET_WIDTH_PERCENT);
@@ -888,7 +890,7 @@ public class BubblePositioner {
* How wide the expanded view should be when showing from the bubble bar.
*/
public int getExpandedViewWidthForBubbleBar(boolean isOverflow) {
- return isOverflow ? mOverflowWidth : mExpandedViewLargeScreenWidth;
+ return isOverflow ? mOverflowWidth : mExpandedViewBubbleBarWidth;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
index e37844f53b11..29fb1a23017c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
@@ -18,6 +18,8 @@ package com.android.wm.shell.bubbles;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.View.INVISIBLE;
import static android.view.WindowManager.TRANSIT_CHANGE;
import android.annotation.NonNull;
@@ -30,8 +32,10 @@ import android.os.IBinder;
import android.util.Slog;
import android.view.SurfaceControl;
import android.view.SurfaceView;
+import android.view.View;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
@@ -53,6 +57,12 @@ import java.util.concurrent.Executor;
public class BubbleTransitions {
private static final String TAG = "BubbleTransitions";
+ /**
+ * Multiplier used to convert a view elevation to an "equivalent" shadow-radius. This is the
+ * same multiple used by skia and surface-outsets in WMS.
+ */
+ private static final float ELEVATION_TO_RADIUS = 2;
+
@NonNull final Transitions mTransitions;
@NonNull final ShellTaskOrganizer mTaskOrganizer;
@NonNull final TaskViewRepository mRepository;
@@ -90,6 +100,44 @@ public class BubbleTransitions {
}
/**
+ * Starts a convert-from-bubble transition.
+ *
+ * @see ConvertFromBubble
+ */
+ public BubbleTransition startConvertFromBubble(Bubble bubble,
+ TaskInfo taskInfo) {
+ ConvertFromBubble convert = new ConvertFromBubble(bubble, taskInfo);
+ return convert;
+ }
+
+ /**
+ * Plucks the task-surface out of an ancestor view while making the view invisible. This helper
+ * attempts to do this seamlessly (ie. view becomes invisible in sync with task reparent).
+ */
+ private void pluck(SurfaceControl taskLeash, View fromView, SurfaceControl dest,
+ float destX, float destY, float cornerRadius, SurfaceControl.Transaction t,
+ Runnable onPlucked) {
+ SurfaceControl.Transaction pluckT = new SurfaceControl.Transaction();
+ pluckT.reparent(taskLeash, dest);
+ t.reparent(taskLeash, dest);
+ pluckT.setPosition(taskLeash, destX, destY);
+ t.setPosition(taskLeash, destX, destY);
+ pluckT.show(taskLeash);
+ pluckT.setAlpha(taskLeash, 1.f);
+ float shadowRadius = fromView.getElevation() * ELEVATION_TO_RADIUS;
+ pluckT.setShadowRadius(taskLeash, shadowRadius);
+ pluckT.setCornerRadius(taskLeash, cornerRadius);
+ t.setShadowRadius(taskLeash, shadowRadius);
+ t.setCornerRadius(taskLeash, cornerRadius);
+
+ // Need to remove the taskview AFTER applying the startTransaction because it isn't
+ // synchronized.
+ pluckT.addTransactionCommittedListener(mMainExecutor, onPlucked::run);
+ fromView.getViewRootImpl().applyTransactionOnDraw(pluckT);
+ fromView.setVisibility(INVISIBLE);
+ }
+
+ /**
* Interface to a bubble-specific transition. Bubble transitions have a multi-step lifecycle
* in order to coordinate with the bubble view logic. These steps are communicated on this
* interface.
@@ -98,6 +146,7 @@ public class BubbleTransitions {
default void surfaceCreated() {}
default void continueExpand() {}
void skip();
+ default void continueCollapse() {}
}
/**
@@ -316,4 +365,154 @@ public class BubbleTransitions {
}
}
}
+
+ /**
+ * BubbleTransition that coordinates the setup for moving a task out of a bubble. The actual
+ * animation is owned by the "receiver" of the task; however, because Bubbles uses TaskView,
+ * we need to do some extra coordination work to get the task surface out of the view
+ * "seamlessly".
+ *
+ * The process here looks like:
+ * 1. Send transition to WM for leaving bubbles mode
+ * 2. in startAnimation, set-up a "pluck" operation to pull the task surface out of taskview
+ * 3. Once "plucked", remove the view (calls continueCollapse when surfaces can be cleaned-up)
+ * 4. Then re-dispatch the transition animation so that the "receiver" can animate it.
+ *
+ * So, constructor -> startAnimation -> continueCollapse -> re-dispatch.
+ */
+ @VisibleForTesting
+ class ConvertFromBubble implements Transitions.TransitionHandler, BubbleTransition {
+ @NonNull final Bubble mBubble;
+ IBinder mTransition;
+ TaskInfo mTaskInfo;
+ SurfaceControl mTaskLeash;
+ SurfaceControl mRootLeash;
+
+ ConvertFromBubble(@NonNull Bubble bubble, TaskInfo taskInfo) {
+ mBubble = bubble;
+ mTaskInfo = taskInfo;
+
+ mBubble.setPreparingTransition(this);
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ WindowContainerToken token = mTaskInfo.getToken();
+ wct.setWindowingMode(token, WINDOWING_MODE_UNDEFINED);
+ wct.setAlwaysOnTop(token, false);
+ mTaskOrganizer.setInterceptBackPressedOnTaskRoot(token, false);
+ mTaskViewTransitions.enqueueExternal(
+ mBubble.getTaskView().getController(),
+ () -> {
+ mTransition = mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
+ return mTransition;
+ });
+ }
+
+ @Override
+ public void skip() {
+ mBubble.setPreparingTransition(null);
+ final TaskViewTaskController tv =
+ mBubble.getTaskView().getController();
+ tv.notifyTaskRemovalStarted(tv.getTaskInfo());
+ mTaskLeash = null;
+ }
+
+ @Override
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @android.annotation.Nullable TransitionRequestInfo request) {
+ return null;
+ }
+
+ @Override
+ public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ }
+
+ @Override
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @NonNull SurfaceControl.Transaction finishTransaction) {
+ if (!aborted) return;
+ mTransition = null;
+ skip();
+ mTaskViewTransitions.onExternalDone(transition);
+ }
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition,
+ @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ if (mTransition != transition) return false;
+
+ final TaskViewTaskController tv =
+ mBubble.getTaskView().getController();
+ if (tv == null) {
+ mTaskViewTransitions.onExternalDone(transition);
+ return false;
+ }
+
+ TransitionInfo.Change taskChg = null;
+
+ boolean found = false;
+ for (int i = 0; i < info.getChanges().size(); ++i) {
+ final TransitionInfo.Change chg = info.getChanges().get(i);
+ if (chg.getTaskInfo() == null) continue;
+ if (chg.getMode() != TRANSIT_CHANGE) continue;
+ if (!mTaskInfo.token.equals(chg.getTaskInfo().token)) continue;
+ found = true;
+ mRepository.remove(tv);
+ taskChg = chg;
+ break;
+ }
+
+ if (!found) {
+ Slog.w(TAG, "Expected a TaskView conversion in this transition but didn't get "
+ + "one, cleaning up the task view");
+ tv.setTaskNotFound();
+ skip();
+ mTaskViewTransitions.onExternalDone(transition);
+ return false;
+ }
+
+ mTaskLeash = taskChg.getLeash();
+ mRootLeash = info.getRoot(0).getLeash();
+
+ SurfaceControl dest =
+ mBubble.getBubbleBarExpandedView().getViewRootImpl().getSurfaceControl();
+ final Runnable onPlucked = () -> {
+ // Need to remove the taskview AFTER applying the startTransaction because
+ // it isn't synchronized.
+ tv.notifyTaskRemovalStarted(tv.getTaskInfo());
+ // Unset after removeView so it can be used to pick a different animation.
+ mBubble.setPreparingTransition(null);
+ mBubbleData.setExpanded(false /* expanded */);
+ };
+ if (dest != null) {
+ pluck(mTaskLeash, mBubble.getBubbleBarExpandedView(), dest,
+ taskChg.getStartAbsBounds().left - info.getRoot(0).getOffset().x,
+ taskChg.getStartAbsBounds().top - info.getRoot(0).getOffset().y,
+ mBubble.getBubbleBarExpandedView().getCornerRadius(), startTransaction,
+ onPlucked);
+ mBubble.getBubbleBarExpandedView().post(() -> mTransitions.dispatchTransition(
+ mTransition, info, startTransaction, finishTransaction, finishCallback,
+ null));
+ } else {
+ onPlucked.run();
+ mTransitions.dispatchTransition(mTransition, info, startTransaction,
+ finishTransaction, finishCallback, null);
+ }
+
+ mTaskViewTransitions.onExternalDone(transition);
+ return true;
+ }
+
+ @Override
+ public void continueCollapse() {
+ mBubble.cleanupTaskView();
+ if (mTaskLeash == null) return;
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ t.reparent(mTaskLeash, mRootLeash);
+ t.apply();
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index 62895fe7c7cc..4297fac0f6a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -36,6 +36,7 @@ import android.window.ScreenCapture.ScreenshotHardwareBuffer;
import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wm.shell.shared.annotations.ExternalThread;
@@ -330,6 +331,18 @@ public interface Bubbles {
* Does not result in a state change.
*/
void animateBubbleBarLocation(BubbleBarLocation location);
+
+ /**
+ * Called when an application icon is being dragged over the Bubble Bar drop zone.
+ * The location of the Bubble Bar is provided as an argument.
+ */
+ void onDragItemOverBubbleBarDragZone(@NonNull BubbleBarLocation location);
+
+ /**
+ * Called when an application icon is being dragged outside the Bubble Bar drop zone.
+ * Always called after {@link #onDragItemOverBubbleBarDragZone(BubbleBarLocation)}
+ */
+ void onItemDraggedOutsideBubbleBarDropZone();
}
/** Listener to find out about stack expansion / collapse events. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl
index eb907dbb6597..9fc769f562a9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubblesListener.aidl
@@ -33,4 +33,16 @@ oneway interface IBubblesListener {
* Does not result in a state change.
*/
void animateBubbleBarLocation(in BubbleBarLocation location);
+
+ /**
+ * Called when an application icon is being dragged over the Bubble Bar drop zone.
+ * The location of the Bubble Bar is provided as an argument.
+ */
+ void onDragItemOverBubbleBarDragZone(in BubbleBarLocation location);
+
+ /**
+ * Called when an application icon is being dragged outside the Bubble Bar drop zone.
+ * Always called after {@link #onDragItemOverBubbleBarDragZone(BubbleBarLocation)}
+ */
+ void onItemDraggedOutsideBubbleBarDropZone();
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
index 91dcbdf5f117..f3f8d6f96a42 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
@@ -355,8 +355,10 @@ public class BubbleBarLayerView extends FrameLayout
/** Removes the given {@code bubble}. */
public void removeBubble(Bubble bubble, Runnable endAction) {
+ final boolean inTransition = bubble.getPreparingTransition() != null;
Runnable cleanUp = () -> {
- bubble.cleanupViews();
+ // The transition is already managing the task/wm state.
+ bubble.cleanupViews(!inTransition);
endAction.run();
};
if (mBubbleData.getBubbles().isEmpty()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
index ad11252364ce..e69d60ddd6c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
@@ -37,7 +37,6 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.BinderThread;
import com.android.window.flags.Flags;
-import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController.OnDisplayChangingListener;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.sysui.ShellInit;
@@ -92,10 +91,7 @@ public class DisplayController {
onDisplayAdded(displayIds[i]);
}
- final boolean enableConnectedDisplayWindowDrag =
- mContext.getResources()
- .getBoolean(R.bool.config_enableConnectedDisplayWindowDrag);
- if (Flags.enableConnectedDisplaysWindowDrag() && enableConnectedDisplayWindowDrag) {
+ if (Flags.enableConnectedDisplaysWindowDrag()) {
mDisplayManager.registerTopologyListener(mMainExecutor,
this::onDisplayTopologyChanged);
onDisplayTopologyChanged(mDisplayManager.getDisplayTopology());
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 dbf95742ca56..72cc3bbc6fc0 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
@@ -114,6 +114,7 @@ import com.android.wm.shell.shared.TransactionPool;
import com.android.wm.shell.shared.annotations.ShellAnimationThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.annotations.ShellSplashscreenThread;
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -258,6 +259,12 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
+ static DesktopModeCompatPolicy provideDesktopModeCompatPolicy(Context context) {
+ return new DesktopModeCompatPolicy(context);
+ }
+
+ @WMSingleton
+ @Provides
static Optional<CompatUIHandler> provideCompatUIController(
Context context,
ShellInit shellInit,
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 c71bf687374d..aadc776c1409 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
@@ -72,7 +72,6 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.UserProfileContexts;
import com.android.wm.shell.common.split.SplitState;
-import com.android.wm.shell.compatui.DesktopModeCompatPolicy;
import com.android.wm.shell.compatui.letterbox.LetterboxCommandHandler;
import com.android.wm.shell.compatui.letterbox.LetterboxTransitionObserver;
import com.android.wm.shell.dagger.back.ShellBackAnimationModule;
@@ -133,6 +132,7 @@ import com.android.wm.shell.shared.TransactionPool;
import com.android.wm.shell.shared.annotations.ShellAnimationThread;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellCommandHandler;
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 883c988a79ca..f275f4c5f829 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
@@ -86,7 +86,6 @@ import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SingleInstanceRemoteListener
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.common.UserProfileContexts
-import com.android.wm.shell.compatui.DesktopModeCompatPolicy
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
@@ -115,6 +114,7 @@ import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_ST
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.annotations.ExternalThread
import com.android.wm.shell.shared.annotations.ShellMainThread
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.DESKTOP_DENSITY_OVERRIDE
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.useDesktopOverrideDensity
@@ -516,10 +516,7 @@ class DesktopTasksController(
remoteTransition: RemoteTransition? = null,
callback: IMoveToDesktopCallback? = null,
) {
- if (
- DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue() &&
- desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(task)
- ) {
+ if (desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(task)) {
logW("Cannot enter desktop for taskId %d, ineligible top activity found", task.taskId)
return
}
@@ -1821,8 +1818,7 @@ class DesktopTasksController(
taskRepository.isActiveTask(triggerTask.taskId))
private fun isIncompatibleTask(task: RunningTaskInfo) =
- DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue() &&
- desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(task)
+ desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(task)
private fun shouldHandleTaskClosing(request: TransitionRequestInfo): Boolean =
ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue() &&
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt
index b698040eca73..224ff37a1dca 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandler.kt
@@ -29,7 +29,6 @@ import androidx.core.animation.addListener
import com.android.app.animation.Interpolators
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.common.ShellExecutor
-import com.android.wm.shell.compatui.DesktopModeCompatPolicy
import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.DesktopWallpaperActivity
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
@@ -37,6 +36,7 @@ import com.android.wm.shell.shared.TransitionUtil.isClosingMode
import com.android.wm.shell.shared.TransitionUtil.isClosingType
import com.android.wm.shell.shared.TransitionUtil.isOpeningMode
import com.android.wm.shell.shared.TransitionUtil.isOpeningType
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TransitionHandler
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 272cb4372acf..03327bf463e3 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
@@ -70,6 +70,7 @@ import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider;
import com.android.wm.shell.pip.PipTransitionController;
+import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip2.animation.PipAlphaAnimator;
import com.android.wm.shell.pip2.animation.PipEnterAnimator;
import com.android.wm.shell.pip2.animation.PipExpandAnimator;
@@ -115,6 +116,7 @@ public class PipTransition extends PipTransitionController implements
private final PipTransitionState mPipTransitionState;
private final PipDisplayLayoutState mPipDisplayLayoutState;
private final DisplayController mDisplayController;
+ private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;
private final Optional<DesktopUserRepositories> mDesktopUserRepositoriesOptional;
private final Optional<DesktopWallpaperActivityTokenProvider>
mDesktopWallpaperActivityTokenProviderOptional;
@@ -171,6 +173,7 @@ public class PipTransition extends PipTransitionController implements
mPipTransitionState.addPipTransitionStateChangedListener(this);
mPipDisplayLayoutState = pipDisplayLayoutState;
mDisplayController = displayController;
+ mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(mContext);
mDesktopUserRepositoriesOptional = desktopUserRepositoriesOptional;
mDesktopWallpaperActivityTokenProviderOptional =
desktopWallpaperActivityTokenProviderOptional;
@@ -343,6 +346,25 @@ public class PipTransition extends PipTransitionController implements
}
}
+ @Override
+ public boolean syncPipSurfaceState(@NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction) {
+ final TransitionInfo.Change pipChange = getPipChange(info);
+ if (pipChange == null) return false;
+
+ // add shadow and corner radii
+ final SurfaceControl leash = pipChange.getLeash();
+ final boolean isInPip = mPipTransitionState.isInPip();
+
+ mPipSurfaceTransactionHelper.round(startTransaction, leash, isInPip)
+ .shadow(startTransaction, leash, isInPip);
+ mPipSurfaceTransactionHelper.round(finishTransaction, leash, isInPip)
+ .shadow(finishTransaction, leash, isInPip);
+
+ return true;
+ }
+
//
// Animation schedulers and entry points
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index aef75e2dc99e..a0cc2bc8887b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -417,7 +417,8 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
}
}
- void notifyTaskRemovalStarted(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
+ /** Notifies listeners of a task being removed. */
+ public void notifyTaskRemovalStarted(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
if (mListener == null) return;
final int taskId = taskInfo.taskId;
mListenerExecutor.execute(() -> mListener.onTaskRemovalStarted(taskId));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index fbe06762277b..ac6e4c5cd69e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -309,7 +309,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
if (TransitionUtil.isAllNoAnimation(info) || TransitionUtil.isAllOrderOnly(info)
|| (info.getFlags() & WindowManager.TRANSIT_FLAG_INVISIBLE) != 0) {
startTransaction.apply();
- finishTransaction.apply();
+ // As a contract, finishTransaction should only be applied in Transitions#onFinish
finishCallback.onTransitionFinished(null /* wct */);
return true;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
index 30ffdac5cbba..357861cc3ca7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
@@ -161,13 +161,10 @@ public class MixedTransitionHelper {
pipHandler.startEnterAnimation(pipChange, startTransaction, finishTransaction,
finishCB);
}
- // make a new finishTransaction because pip's startEnterAnimation "consumes" it so
- // we need a separate one to send over to launcher.
- SurfaceControl.Transaction otherFinishT = new SurfaceControl.Transaction();
// Dispatch the rest of the transition normally. This will most-likely be taken by
// recents or default handler.
mixed.mLeftoversHandler = player.dispatchTransition(mixed.mTransition, everythingElse,
- otherStartT, otherFinishT, finishCB, mixedHandler);
+ otherStartT, finishTransaction, finishCB, mixedHandler);
} else {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Not leaving split, so just "
+ "forward animation to Pip-Handler.");
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 46c5048b2147..2cf574158358 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
@@ -108,7 +108,6 @@ import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIController;
-import com.android.wm.shell.compatui.DesktopModeCompatPolicy;
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler;
import com.android.wm.shell.desktopmode.DesktopImmersiveController;
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
@@ -133,6 +132,7 @@ import com.android.wm.shell.recents.RecentsTransitionStateListener;
import com.android.wm.shell.shared.FocusTransitionListener;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource;
import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition;
@@ -1657,8 +1657,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
&& mSplitScreenController.isTaskRootOrStageRoot(taskInfo.taskId)) {
return false;
}
- if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue()
- && mDesktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(taskInfo)) {
+ if (mDesktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(taskInfo)) {
return false;
}
if (isPartOfDefaultHomePackage(taskInfo)) {
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 fe9bdb027d18..dd7488e5f2f9 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
@@ -972,7 +972,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
final RelayoutParams.OccludingCaptionElement controlsElement =
new RelayoutParams.OccludingCaptionElement();
controlsElement.mWidthResId = R.dimen.desktop_mode_customizable_caption_margin_end;
- if (Flags.enableMinimizeButton()) {
+ if (DesktopModeFlags.ENABLE_MINIMIZE_BUTTON.isTrue()) {
controlsElement.mWidthResId =
R.dimen.desktop_mode_customizable_caption_with_minimize_button_margin_end;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
index 33f0432372d0..07496eb0e526 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
@@ -29,7 +29,6 @@ import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import com.android.internal.jank.Cuj
import com.android.internal.jank.InteractionJankMonitor
-import com.android.wm.shell.R
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.MultiDisplayDragMoveBoundsCalculator
@@ -68,8 +67,6 @@ class MultiDisplayVeiledResizeTaskPositioner(
(ctrlType and DragPositioningCallback.CTRL_TYPE_LEFT) != 0 ||
(ctrlType and DragPositioningCallback.CTRL_TYPE_RIGHT) != 0
- private val enableMultiDisplayWindowDrag: Boolean
-
@DragPositioningCallback.CtrlType private var ctrlType = 0
private var isResizingOrAnimatingResize = false
@Surface.Rotation private var rotation = 0
@@ -96,10 +93,6 @@ class MultiDisplayVeiledResizeTaskPositioner(
init {
dragEventListeners.add(dragEventListener)
- enableMultiDisplayWindowDrag =
- desktopWindowDecoration.mDecorWindowContext.resources.getBoolean(
- R.bool.config_enableConnectedDisplayWindowDrag
- )
}
override fun onDragPositioningStart(ctrlType: Int, displayId: Int, x: Float, y: Float): Rect {
@@ -175,13 +168,8 @@ class MultiDisplayVeiledResizeTaskPositioner(
val startDisplayLayout = displayController.getDisplayLayout(startDisplayId)
val currentDisplayLayout = displayController.getDisplayLayout(displayId)
- if (
- startDisplayLayout == null ||
- currentDisplayLayout == null ||
- !enableMultiDisplayWindowDrag
- ) {
- // Fall back to single-display drag behavior if any display layout is unavailable or
- // it's explicitly disabled.
+ if (startDisplayLayout == null || currentDisplayLayout == null) {
+ // Fall back to single-display drag behavior if any display layout is unavailable.
DragPositioningCallbackUtility.setPositionOnDrag(
desktopWindowDecoration,
repositionTaskBounds,
@@ -249,13 +237,8 @@ class MultiDisplayVeiledResizeTaskPositioner(
val startDisplayLayout = displayController.getDisplayLayout(startDisplayId)
val currentDisplayLayout = displayController.getDisplayLayout(displayId)
- if (
- startDisplayLayout == null ||
- currentDisplayLayout == null ||
- !enableMultiDisplayWindowDrag
- ) {
- // Fall back to single-display drag behavior if any display layout is unavailable or
- // it's explicitly disabled.
+ if (startDisplayLayout == null || currentDisplayLayout == null) {
+ // Fall back to single-display drag behavior if any display layout is unavailable.
DragPositioningCallbackUtility.updateTaskBounds(
repositionTaskBounds,
taskBoundsAtDragStart,
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 79c5eff01b4c..9f8ca7740182 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
@@ -47,7 +47,6 @@ import com.android.internal.R.color.materialColorSurfaceContainerHigh
import com.android.internal.R.color.materialColorSurfaceContainerLow
import com.android.internal.R.color.materialColorSurfaceDim
import com.android.window.flags.Flags
-import com.android.window.flags.Flags.enableMinimizeButton
import com.android.wm.shell.R
import android.window.DesktopModeFlags
import com.android.wm.shell.windowdecor.MaximizeButtonView
@@ -226,7 +225,7 @@ class AppHeaderViewHolder(
minimizeWindowButton.background = getDrawable(1)
}
maximizeButtonView.setAnimationTints(isDarkMode())
- minimizeWindowButton.isGone = !enableMinimizeButton()
+ minimizeWindowButton.isGone = !DesktopModeFlags.ENABLE_MINIMIZE_BUTTON.isTrue()
}
private fun bindDataWithThemedHeaders(
@@ -276,7 +275,7 @@ class AppHeaderViewHolder(
drawableInsets = minimizeDrawableInsets
)
}
- minimizeWindowButton.isGone = !enableMinimizeButton()
+ minimizeWindowButton.isGone = !DesktopModeFlags.ENABLE_MINIMIZE_BUTTON.isTrue()
// Maximize button.
maximizeButtonView.apply {
setAnimationTints(
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/CopyContentInSplit.kt
index 31d89f92f744..9d501d32fbc7 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/CopyContentInSplit.kt
@@ -23,8 +23,8 @@ import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.RecentTasksUtils
import com.android.wm.shell.Utils
-import com.android.wm.shell.flicker.utils.RecentTasksUtils
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByDivider.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByDivider.kt
index 1af6cac39085..f574f02ac3b3 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByDivider.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByDivider.kt
@@ -23,8 +23,8 @@ import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.RecentTasksUtils
import com.android.wm.shell.Utils
-import com.android.wm.shell.flicker.utils.RecentTasksUtils
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByGoHome.kt
index 8ad8c7bd7a7f..60fcce2fbf18 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByGoHome.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DismissSplitScreenByGoHome.kt
@@ -23,8 +23,8 @@ import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.RecentTasksUtils
import com.android.wm.shell.Utils
-import com.android.wm.shell.flicker.utils.RecentTasksUtils
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DragDividerToResize.kt
index da0ace472153..e6a080b2d258 100644
--- a/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DragDividerToResize.kt
+++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/scenarios/src/com/android/wm/shell/scenarios/DragDividerToResize.kt
@@ -23,8 +23,8 @@ import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.RecentTasksUtils
import com.android.wm.shell.Utils
-import com.android.wm.shell.flicker.utils.RecentTasksUtils
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java
index b4f514acf2dd..9d0ddbc6de12 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java
@@ -179,4 +179,33 @@ public class BubbleTransitionsTest extends ShellTestCase {
animCb.getValue().run();
assertTrue(finishCalled[0]);
}
+
+ @Test
+ public void testConvertFromBubble() {
+ ActivityManager.RunningTaskInfo taskInfo = setupBubble();
+ final BubbleTransitions.BubbleTransition bt = mBubbleTransitions.startConvertFromBubble(
+ mBubble, taskInfo);
+ final BubbleTransitions.ConvertFromBubble cfb = (BubbleTransitions.ConvertFromBubble) bt;
+ verify(mTransitions).startTransition(anyInt(), any(), eq(cfb));
+ verify(mBubble).setPreparingTransition(eq(bt));
+ assertTrue(mTaskViewTransitions.hasPending());
+
+ final TransitionInfo info = new TransitionInfo(TRANSIT_CHANGE, 0);
+ final TransitionInfo.Change chg = new TransitionInfo.Change(taskInfo.token,
+ mock(SurfaceControl.class));
+ chg.setMode(TRANSIT_CHANGE);
+ chg.setTaskInfo(taskInfo);
+ info.addChange(chg);
+ info.addRoot(new TransitionInfo.Root(0, mock(SurfaceControl.class), 0, 0));
+ SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ Transitions.TransitionFinishCallback finishCb = wct -> {};
+ cfb.startAnimation(cfb.mTransition, info, startT, finishT, finishCb);
+
+ // Can really only verify that it interfaces with the taskViewTransitions queue.
+ // The actual functioning of this is tightly-coupled with SurfaceFlinger and renderthread
+ // in order to properly synchronize surface manipulation with drawing and thus can't be
+ // directly tested.
+ assertFalse(mTaskViewTransitions.hasPending());
+ }
}
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 774fd4e510d2..8a76526a321d 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
@@ -101,7 +101,6 @@ import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.common.UserProfileContexts
-import com.android.wm.shell.compatui.DesktopModeCompatPolicy
import com.android.wm.shell.desktopmode.DesktopImmersiveController.ExitResult
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason
@@ -130,6 +129,7 @@ import com.android.wm.shell.recents.RecentsTransitionHandler
import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_ANIMATING
import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource.UNKNOWN
import com.android.wm.shell.shared.split.SplitScreenConstants
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
index b750684ae23c..dfb1b0c8c642 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
@@ -26,7 +26,6 @@ import android.view.WindowManager.TRANSIT_OPEN
import androidx.test.filters.SmallTest
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.ShellExecutor
-import com.android.wm.shell.compatui.DesktopModeCompatPolicy
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTaskBuilder
@@ -34,6 +33,7 @@ import com.android.wm.shell.desktopmode.DesktopTestHelpers.createSystemModalTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createSystemModalTaskBuilder
import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.DesktopWallpaperActivity
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.TransitionInfoBuilder
import com.android.wm.shell.transition.Transitions
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/DesktopModeCompatPolicyTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
index e894297d5ea2..8c78debdc19f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/DesktopModeCompatPolicyTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package com.android.wm.shell.compatui
+package com.android.wm.shell.shared.desktopmode
import android.content.ComponentName
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.internal.R
+import com.android.wm.shell.compatui.CompatUIShellTestCase
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
index 98529b5aa06d..c5c827467c75 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
@@ -55,7 +55,6 @@ import com.android.wm.shell.common.DisplayInsetsController
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.SyncTransactionQueue
-import com.android.wm.shell.compatui.DesktopModeCompatPolicy
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler
import com.android.wm.shell.desktopmode.DesktopImmersiveController
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
@@ -70,6 +69,7 @@ import com.android.wm.shell.desktopmode.education.AppToWebEducationController
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
import com.android.wm.shell.recents.RecentsTransitionHandler
import com.android.wm.shell.recents.RecentsTransitionStateListener
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 52eae43f7db9..71013f7f4e34 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -21,6 +21,8 @@ import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
+import static android.media.audio.Flags.cacheGetStreamMinMaxVolume;
+import static android.media.audio.Flags.cacheGetStreamVolume;
import static android.media.audio.Flags.FLAG_DEPRECATE_STREAM_BT_SCO;
import static android.media.audio.Flags.FLAG_FOCUS_EXCLUSIVE_WITH_RECORDING;
import static android.media.audio.Flags.FLAG_FOCUS_FREEZE_TEST_API;
@@ -58,7 +60,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.AudioAttributes.AttributeSystemUsage;
-import android.media.AudioDeviceInfo;
import android.media.CallbackUtil.ListenerInfo;
import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
@@ -75,6 +76,7 @@ import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IpcDataCache;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
@@ -1231,6 +1233,102 @@ public class AudioManager {
}
/**
+ * API string for caching the min volume for each stream
+ * @hide
+ **/
+ public static final String VOLUME_MIN_CACHING_API = "getStreamMinVolume";
+ /**
+ * API string for caching the max volume for each stream
+ * @hide
+ **/
+ public static final String VOLUME_MAX_CACHING_API = "getStreamMaxVolume";
+ /**
+ * API string for caching the volume for each stream
+ * @hide
+ **/
+ public static final String VOLUME_CACHING_API = "getStreamVolume";
+ private static final int VOLUME_CACHING_SIZE = 16;
+
+ private final IpcDataCache.QueryHandler<VolumeCacheQuery, Integer> mVolQuery =
+ new IpcDataCache.QueryHandler<>() {
+ @Override
+ public Integer apply(VolumeCacheQuery query) {
+ final IAudioService service = getService();
+ try {
+ return switch (query.queryCommand) {
+ case QUERY_VOL_MIN -> service.getStreamMinVolume(query.stream);
+ case QUERY_VOL_MAX -> service.getStreamMaxVolume(query.stream);
+ case QUERY_VOL -> service.getStreamVolume(query.stream);
+ default -> {
+ Log.w(TAG, "Not a valid volume cache query: " + query);
+ yield null;
+ }
+ };
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ };
+
+ private final IpcDataCache<VolumeCacheQuery, Integer> mVolMinCache =
+ new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
+ VOLUME_MIN_CACHING_API, VOLUME_MIN_CACHING_API, mVolQuery);
+
+ private final IpcDataCache<VolumeCacheQuery, Integer> mVolMaxCache =
+ new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
+ VOLUME_MAX_CACHING_API, VOLUME_MAX_CACHING_API, mVolQuery);
+
+ private final IpcDataCache<VolumeCacheQuery, Integer> mVolCache =
+ new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
+ VOLUME_CACHING_API, VOLUME_CACHING_API, mVolQuery);
+
+ /**
+ * Used to invalidate the cache for the given API
+ * @hide
+ **/
+ public static void clearVolumeCache(String api) {
+ if (cacheGetStreamMinMaxVolume() && (VOLUME_MAX_CACHING_API.equals(api)
+ || VOLUME_MIN_CACHING_API.equals(api))) {
+ IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, api);
+ } else if (cacheGetStreamVolume() && VOLUME_CACHING_API.equals(api)) {
+ IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, api);
+ } else {
+ Log.w(TAG, "invalid clearVolumeCache for api " + api);
+ }
+ }
+
+ private static final int QUERY_VOL_MIN = 1;
+ private static final int QUERY_VOL_MAX = 2;
+ private static final int QUERY_VOL = 3;
+ /** @hide */
+ @IntDef(prefix = "QUERY_VOL", value = {
+ QUERY_VOL_MIN,
+ QUERY_VOL_MAX,
+ QUERY_VOL}
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface QueryVolCommand {}
+
+ private record VolumeCacheQuery(int stream, @QueryVolCommand int queryCommand) {
+ private String queryVolCommandToString() {
+ return switch (queryCommand) {
+ case QUERY_VOL_MIN -> "getStreamMinVolume";
+ case QUERY_VOL_MAX -> "getStreamMaxVolume";
+ case QUERY_VOL -> "getStreamVolume";
+ default -> "invalid command";
+ };
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return TextUtils.formatSimple("VolumeCacheQuery(stream=%d, queryCommand=%s)", stream,
+ queryVolCommandToString());
+ }
+ }
+
+ /**
* Returns the maximum volume index for a particular stream.
*
* @param streamType The stream type whose maximum volume index is returned.
@@ -1238,6 +1336,9 @@ public class AudioManager {
* @see #getStreamVolume(int)
*/
public int getStreamMaxVolume(int streamType) {
+ if (cacheGetStreamMinMaxVolume()) {
+ return mVolMaxCache.query(new VolumeCacheQuery(streamType, QUERY_VOL_MAX));
+ }
final IAudioService service = getService();
try {
return service.getStreamMaxVolume(streamType);
@@ -1271,6 +1372,9 @@ public class AudioManager {
*/
@TestApi
public int getStreamMinVolumeInt(int streamType) {
+ if (cacheGetStreamMinMaxVolume()) {
+ return mVolMinCache.query(new VolumeCacheQuery(streamType, QUERY_VOL_MIN));
+ }
final IAudioService service = getService();
try {
return service.getStreamMinVolume(streamType);
@@ -1288,6 +1392,9 @@ public class AudioManager {
* @see #setStreamVolume(int, int, int)
*/
public int getStreamVolume(int streamType) {
+ if (cacheGetStreamVolume()) {
+ return mVolCache.query(new VolumeCacheQuery(streamType, QUERY_VOL));
+ }
final IAudioService service = getService();
try {
return service.getStreamVolume(streamType);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index c9625c405faa..c4886836f451 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -20,6 +20,8 @@ import static android.media.codec.Flags.FLAG_CODEC_AVAILABILITY;
import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE;
import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
import static android.media.codec.Flags.FLAG_SUBSESSION_METRICS;
+import static android.media.tv.flags.Flags.applyPictureProfiles;
+import static android.media.tv.flags.Flags.mediaQualityFw;
import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME;
@@ -37,6 +39,8 @@ import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.HardwareBuffer;
import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.quality.PictureProfile;
+import android.media.quality.PictureProfileHandle;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -5370,6 +5374,9 @@ final public class MediaCodec {
* @param params The bundle of parameters to set.
* @throws IllegalStateException if in the Released state.
*/
+
+ private static final String PARAMETER_KEY_PICTURE_PROFILE_HANDLE = "picture-profile-handle";
+
public final void setParameters(@Nullable Bundle params) {
if (params == null) {
return;
@@ -5383,19 +5390,41 @@ final public class MediaCodec {
if (key.equals(MediaFormat.KEY_AUDIO_SESSION_ID)) {
int sessionId = 0;
try {
- sessionId = (Integer)params.get(key);
+ sessionId = (Integer) params.get(key);
} catch (Exception e) {
throw new IllegalArgumentException("Wrong Session ID Parameter!");
}
keys[i] = "audio-hw-sync";
values[i] = AudioSystem.getAudioHwSyncForSession(sessionId);
+ } else if (applyPictureProfiles() && mediaQualityFw()
+ && key.equals(MediaFormat.KEY_PICTURE_PROFILE_INSTANCE)) {
+ PictureProfile pictureProfile = null;
+ try {
+ pictureProfile = (PictureProfile) params.get(key);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(
+ "Cannot cast the instance parameter to PictureProfile!");
+ } catch (Exception e) {
+ android.util.Log.getStackTraceString(e);
+ throw new IllegalArgumentException("Unexpected exception when casting the "
+ + "instance parameter to PictureProfile!");
+ }
+ if (pictureProfile == null) {
+ throw new IllegalArgumentException(
+ "Picture profile instance parameter is null!");
+ }
+ PictureProfileHandle handle = pictureProfile.getHandle();
+ if (handle != PictureProfileHandle.NONE) {
+ keys[i] = PARAMETER_KEY_PICTURE_PROFILE_HANDLE;
+ values[i] = Long.valueOf(handle.getId());
+ }
} else {
keys[i] = key;
Object value = params.get(key);
// Bundle's byte array is a byte[], JNI layer only takes ByteBuffer
if (value instanceof byte[]) {
- values[i] = ByteBuffer.wrap((byte[])value);
+ values[i] = ByteBuffer.wrap((byte[]) value);
} else {
values[i] = value;
}
diff --git a/media/java/android/media/quality/MediaQualityContract.java b/media/java/android/media/quality/MediaQualityContract.java
index d1f63404dbff..8ae72de3214a 100644
--- a/media/java/android/media/quality/MediaQualityContract.java
+++ b/media/java/android/media/quality/MediaQualityContract.java
@@ -385,6 +385,339 @@ public class MediaQualityContract {
public static final String PARAMETER_AUTO_SUPER_RESOLUTION_ENABLED =
"auto_super_resolution_enabled";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_LEVEL_RANGE = "level_range";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_GAMUT_MAPPING = "gamut_mapping";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_PC_MODE = "pc_mode";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_LOW_LATENCY = "low_latency";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_VRR = "vrr";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_CVRR = "cvrr";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_HDMI_RGB_RANGE = "hdmi_rgb_range";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_SPACE = "color_space";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_PANEL_INIT_MAX_LUMINCE_NITS =
+ "panel_init_max_lumince_nits";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_PANEL_INIT_MAX_LUMINCE_VALID =
+ "panel_init_max_lumince_valid";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_GAMMA = "gamma";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TEMPERATURE_RED_OFFSET =
+ "color_temperature_red_offset";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TEMPERATURE_GREEN_OFFSET =
+ "color_temperature_green_offset";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TEMPERATURE_BLUE_OFFSET =
+ "color_temperature_blue_offset";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_ELEVEN_POINT_RED = "eleven_point_red";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_ELEVEN_POINT_GREEN = "eleven_point_green";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_ELEVEN_POINT_BLUE = "eleven_point_blue";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_LOW_BLUE_LIGHT = "low_blue_light";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_LD_MODE = "ld_mode";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_RED_GAIN = "osd_red_gain";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_GREEN_GAIN = "osd_green_gain";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_BLUE_GAIN = "osd_blue_gain";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_RED_OFFSET = "osd_red_offset";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_GREEN_OFFSET = "osd_green_offset";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_BLUE_OFFSET = "osd_blue_offset";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_HUE = "osd_hue";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_SATURATION = "osd_saturation";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_OSD_CONTRAST = "osd_contrast";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SWITCH = "color_tuner_switch";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_HUE_RED = "color_tuner_hue_red";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_HUE_GREEN = "color_tuner_hue_green";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_HUE_BLUE = "color_tuner_hue_blue";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_HUE_CYAN = "color_tuner_hue_cyan";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_HUE_MAGENTA = "color_tuner_hue_magenta";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_HUE_YELLOW = "color_tuner_hue_yellow";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_HUE_FLESH = "color_tuner_hue_flesh";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SATURATION_RED =
+ "color_tuner_saturation_red";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SATURATION_GREEN =
+ "color_tuner_saturation_green";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SATURATION_BLUE =
+ "color_tuner_saturation_blue";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SATURATION_CYAN =
+ "color_tuner_saturation_cyan";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SATURATION_MAGENTA =
+ "color_tuner_saturation_magenta";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SATURATION_YELLOW =
+ "color_tuner_saturation_yellow";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_SATURATION_FLESH =
+ "color_tuner_saturation_flesh";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_LUMINANCE_RED =
+ "color_tuner_luminance_red";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_LUMINANCE_GREEN =
+ "color_tuner_luminance_green";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_LUMINANCE_BLUE =
+ "color_tuner_luminance_blue";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_LUMINANCE_CYAN =
+ "color_tuner_luminance_cyan";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_LUMINANCE_MAGENTA =
+ "color_tuner_luminance_magenta";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_LUMINANCE_YELLOW =
+ "color_tuner_luminance_yellow";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_COLOR_TUNER_LUMINANCE_FLESH =
+ "color_tuner_luminance_flesh";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_ACTIVE_PROFILE = "active_profile";
+
+ /**
+ * @hide
+ *
+ */
+ public static final String PARAMETER_PICTURE_QUALITY_EVENT_TYPE =
+ "picture_quality_event_type";
+
private PictureQuality() {
}
}
@@ -641,6 +974,17 @@ public class MediaQualityContract {
*/
public static final String PARAMETER_DIGITAL_OUTPUT_MODE = "digital_output_mode";
+ /**
+ * @hide
+ */
+ public static final String PARAMETER_ACTIVE_PROFILE = "active_profile";
+
+ /**
+ * @hide
+ */
+ public static final String PARAMETER_SOUND_STYLE = "sound_style";
+
+
private SoundQuality() {
}
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index a77bc9fe0570..a1ce495fe33d 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -910,7 +910,7 @@ MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
case MTP_FORMAT_TIFF:
case MTP_FORMAT_TIFF_EP:
case MTP_FORMAT_DEFINED: {
- String8 temp(path);
+ String8 temp {static_cast<std::string_view>(path)};
std::unique_ptr<FileStream> stream(new FileStream(temp));
piex::PreviewImageData image_data;
if (!GetExifFromRawImage(stream.get(), temp, image_data)) {
@@ -967,7 +967,7 @@ void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
case MTP_FORMAT_TIFF:
case MTP_FORMAT_TIFF_EP:
case MTP_FORMAT_DEFINED: {
- String8 temp(path);
+ String8 temp {static_cast<std::string_view>(path)};
std::unique_ptr<FileStream> stream(new FileStream(temp));
piex::PreviewImageData image_data;
if (!GetExifFromRawImage(stream.get(), temp, image_data)) {
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
index e9a0d3eceba3..209734ca4a53 100644
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
@@ -16,6 +16,15 @@
package com.android.audiopolicytest;
+import static android.media.AudioManager.STREAM_ACCESSIBILITY;
+import static android.media.AudioManager.STREAM_ALARM;
+import static android.media.AudioManager.STREAM_DTMF;
+import static android.media.AudioManager.STREAM_MUSIC;
+import static android.media.AudioManager.STREAM_NOTIFICATION;
+import static android.media.AudioManager.STREAM_RING;
+import static android.media.AudioManager.STREAM_SYSTEM;
+import static android.media.AudioManager.STREAM_VOICE_CALL;
+
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.android.audiopolicytest.AudioVolumeTestUtil.DEFAULT_ATTRIBUTES;
@@ -28,11 +37,15 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
+import android.media.IAudioService;
import android.media.audiopolicy.AudioProductStrategy;
import android.media.audiopolicy.AudioVolumeGroup;
+import android.os.IBinder;
+import android.os.ServiceManager;
import android.platform.test.annotations.Presubmit;
import android.util.Log;
@@ -54,6 +67,17 @@ public class AudioManagerTest {
private AudioManager mAudioManager;
+ private static final int[] PUBLIC_STREAM_TYPES = {
+ STREAM_VOICE_CALL,
+ STREAM_SYSTEM,
+ STREAM_RING,
+ STREAM_MUSIC,
+ STREAM_ALARM,
+ STREAM_NOTIFICATION,
+ STREAM_DTMF,
+ STREAM_ACCESSIBILITY,
+ };
+
@Rule
public final AudioVolumesTestRule rule = new AudioVolumesTestRule();
@@ -207,6 +231,33 @@ public class AudioManagerTest {
}
//-----------------------------------------------------------------
+ // Test getStreamVolume consistency with AudioService
+ //-----------------------------------------------------------------
+ @Test
+ public void getStreamMinMaxVolume_consistentWithAs() throws Exception {
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ IAudioService service = IAudioService.Stub.asInterface(b);
+
+ for (int streamType : PUBLIC_STREAM_TYPES) {
+ assertEquals(service.getStreamMinVolume(streamType),
+ mAudioManager.getStreamMinVolume(streamType));
+ assertEquals(service.getStreamMaxVolume(streamType),
+ mAudioManager.getStreamMaxVolume(streamType));
+ }
+ }
+
+ @Test
+ public void getStreamVolume_consistentWithAs() throws Exception {
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ IAudioService service = IAudioService.Stub.asInterface(b);
+
+ for (int streamType : PUBLIC_STREAM_TYPES) {
+ assertEquals(service.getStreamVolume(streamType),
+ mAudioManager.getStreamVolume(streamType));
+ }
+ }
+
+ //-----------------------------------------------------------------
// Test Volume per Attributes setter/getters
//-----------------------------------------------------------------
@Test
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index fe27cee7ba2d..acead8e2a0eb 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -510,7 +510,10 @@ public final class PageContentRepository {
protected Void doInBackground(Void... params) {
synchronized (mLock) {
try {
- if (mRenderer != null) {
+ // A page count < 0 indicates there was an error
+ // opening the document, in which case it doesn't
+ // need to be closed.
+ if (mRenderer != null && mPageCount >= 0) {
mRenderer.closeDocument();
}
} catch (RemoteException re) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index b48c55ddfef0..a9d00e9a77eb 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -70,6 +70,7 @@ public final class RemotePrintDocument {
private static final int STATE_CANCELING = 6;
private static final int STATE_CANCELED = 7;
private static final int STATE_DESTROYED = 8;
+ private static final int STATE_INVALID = 9;
private final Context mContext;
@@ -287,7 +288,8 @@ public final class RemotePrintDocument {
}
if (mState != STATE_STARTED && mState != STATE_UPDATED
&& mState != STATE_FAILED && mState != STATE_CANCELING
- && mState != STATE_CANCELED && mState != STATE_DESTROYED) {
+ && mState != STATE_CANCELED && mState != STATE_DESTROYED
+ && mState != STATE_INVALID) {
throw new IllegalStateException("Cannot finish in state:"
+ stateToString(mState));
}
@@ -300,6 +302,16 @@ public final class RemotePrintDocument {
}
}
+ /**
+ * Mark this document as invalid.
+ */
+ public void invalid() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[CALLED] invalid()");
+ }
+ mState = STATE_INVALID;
+ }
+
public void cancel(boolean force) {
if (DEBUG) {
Log.i(LOG_TAG, "[CALLED] cancel(" + force + ")");
@@ -491,6 +503,9 @@ public final class RemotePrintDocument {
case STATE_DESTROYED: {
return "STATE_DESTROYED";
}
+ case STATE_INVALID: {
+ return "STATE_INVALID";
+ }
default: {
return "STATE_UNKNOWN";
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 4a3a6d248254..2e3234e6e622 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -167,6 +167,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private static final int STATE_PRINTER_UNAVAILABLE = 6;
private static final int STATE_UPDATE_SLOW = 7;
private static final int STATE_PRINT_COMPLETED = 8;
+ private static final int STATE_FILE_INVALID = 9;
private static final int UI_STATE_PREVIEW = 0;
private static final int UI_STATE_ERROR = 1;
@@ -404,6 +405,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
public void onPause() {
PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
+ if (isInvalid()) {
+ super.onPause();
+ return;
+ }
+
if (mState == STATE_INITIALIZING) {
if (isFinishing()) {
if (spooler != null) {
@@ -478,7 +484,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
if (mState == STATE_PRINT_CANCELED || mState == STATE_PRINT_CONFIRMED
- || mState == STATE_PRINT_COMPLETED) {
+ || mState == STATE_PRINT_COMPLETED
+ || mState == STATE_FILE_INVALID) {
return true;
}
@@ -509,23 +516,32 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
@Override
public void onMalformedPdfFile() {
onPrintDocumentError("Cannot print a malformed PDF file");
+ mPrintedDocument.invalid();
+ setState(STATE_FILE_INVALID);
}
@Override
public void onSecurePdfFile() {
onPrintDocumentError("Cannot print a password protected PDF file");
+ mPrintedDocument.invalid();
+ setState(STATE_FILE_INVALID);
}
private void onPrintDocumentError(String message) {
setState(mProgressMessageController.cancel());
- ensureErrorUiShown(null, PrintErrorFragment.ACTION_RETRY);
+ ensureErrorUiShown(
+ getString(R.string.print_cannot_load_page), PrintErrorFragment.ACTION_NONE);
setState(STATE_UPDATE_FAILED);
if (DEBUG) {
Log.i(LOG_TAG, "PrintJob state[" + PrintJobInfo.STATE_FAILED + "] reason: " + message);
}
PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
- spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_FAILED, message);
+ // Use a cancel state for the spooler. This will prevent the notification from getting
+ // displayed and will remove the job. The notification (which displays the cancel and
+ // restart options) doesn't make sense for an invalid document since it will just fail
+ // again.
+ spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, message);
mPrintedDocument.finish();
}
@@ -995,6 +1011,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
private void setState(int state) {
+ if (isInvalid()) {
+ return;
+ }
if (isFinalState(mState)) {
if (isFinalState(state)) {
if (DEBUG) {
@@ -1015,7 +1034,12 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private static boolean isFinalState(int state) {
return state == STATE_PRINT_CANCELED
|| state == STATE_PRINT_COMPLETED
- || state == STATE_CREATE_FILE_FAILED;
+ || state == STATE_CREATE_FILE_FAILED
+ || state == STATE_FILE_INVALID;
+ }
+
+ private boolean isInvalid() {
+ return mState == STATE_FILE_INVALID;
}
private void updateSelectedPagesFromPreview() {
@@ -1100,7 +1124,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
private void ensurePreviewUiShown() {
- if (isFinishing() || isDestroyed()) {
+ if (isFinishing() || isDestroyed() || isInvalid()) {
return;
}
if (mUiState != UI_STATE_PREVIEW) {
@@ -1257,6 +1281,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
private boolean updateDocument(boolean clearLastError) {
+ if (isInvalid()) {
+ return false;
+ }
if (!clearLastError && mPrintedDocument.hasUpdateError()) {
return false;
}
@@ -1676,7 +1703,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
|| mState == STATE_UPDATE_FAILED
|| mState == STATE_CREATE_FILE_FAILED
|| mState == STATE_PRINTER_UNAVAILABLE
- || mState == STATE_UPDATE_SLOW) {
+ || mState == STATE_UPDATE_SLOW
+ || mState == STATE_FILE_INVALID) {
disableOptionsUi(isFinalState(mState));
return;
}
@@ -2100,6 +2128,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
private boolean canUpdateDocument() {
+ if (isInvalid()) {
+ return false;
+ }
if (mPrintedDocument.isDestroyed()) {
return false;
}
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled.xml
index f55b320269a8..ff22b2e7f86f 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_extra.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_extra.xml
index b663b6ccc5bf..d878ba0d310b 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_extra.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_extra.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_large.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_large.xml
index 784e6ad6a9f8..8f0a158c55eb 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_large.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_filled_large.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline.xml
index 8b44a6539801..0c8996063e9f 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_extra.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_extra.xml
index f8a2d8fbd975..41d8490feeb3 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_extra.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_extra.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_large.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_large.xml
index 781a5a136164..958552064c98 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_large.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_outline_large.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal.xml
index 5b568f870ea4..03ca1f0a1033 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_extra.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_extra.xml
index 1e7a08b714f1..030ee66fef3f 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_extra.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_extra.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_large.xml b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_large.xml
index 42116be07041..5c16723f7a63 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_large.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout-v35/settingslib_expressive_button_tonal_large.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout/settingslib_button_layout.xml b/packages/SettingsLib/ButtonPreference/res/layout/settingslib_button_layout.xml
index 1ff09901ffaf..5405045a013d 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout/settingslib_button_layout.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout/settingslib_button_layout.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:filterTouchesWhenObscured="true">
<Button
android:id="@+id/settingslib_button"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout/settingslib_number_button.xml b/packages/SettingsLib/ButtonPreference/res/layout/settingslib_number_button.xml
index fa13b4125065..b23c5a510745 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout/settingslib_number_button.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout/settingslib_number_button.xml
@@ -29,7 +29,8 @@
android:layout_height="wrap_content"
android:paddingVertical="@dimen/settingslib_expressive_space_small1"
android:paddingHorizontal="@dimen/settingslib_expressive_space_small4"
- android:background="@drawable/settingslib_number_button_background">
+ android:background="@drawable/settingslib_number_button_background"
+ android:filterTouchesWhenObscured="true">
<TextView
android:id="@+id/settingslib_number_count"
android:layout_width="wrap_content"
diff --git a/packages/SettingsLib/ButtonPreference/res/layout/settingslib_section_button.xml b/packages/SettingsLib/ButtonPreference/res/layout/settingslib_section_button.xml
index e7fb572d06dc..66a4c2e25c77 100644
--- a/packages/SettingsLib/ButtonPreference/res/layout/settingslib_section_button.xml
+++ b/packages/SettingsLib/ButtonPreference/res/layout/settingslib_section_button.xml
@@ -21,7 +21,8 @@
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingVertical="@dimen/settingslib_expressive_space_extrasmall4">
+ android:paddingVertical="@dimen/settingslib_expressive_space_extrasmall4"
+ android:filterTouchesWhenObscured="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/settingslib_section_button"
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt
index 3309faaa8db2..3a6327962dc2 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt
@@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.flowOn
data class EnhancedConfirmation(
val key: String,
val packageName: String,
+ val isRestrictedSettingAllowed: Boolean?
)
data class Restrictions(
val userId: Int = UserHandle.myUserId(),
@@ -92,6 +93,9 @@ internal class RestrictionsProviderImpl(
}
restrictions.enhancedConfirmation?.let { ec ->
+ if (ec.isRestrictedSettingAllowed == true) {
+ return NoRestricted
+ }
RestrictedLockUtilsInternal
.checkIfRequiresEnhancedConfirmation(context, ec.key,
ec.packageName)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index 7466f95e3fb8..5580d2e3211b 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -155,7 +155,7 @@ internal fun <T : AppRecord> TogglePermissionAppListModel<T>.TogglePermissionApp
}
RestrictedSwitchPreference(
model = switchModel,
- restrictions = getRestrictions(userId, packageName),
+ restrictions = getRestrictions(userId, packageName, isAllowed()),
ifBlockedByAdminOverrideCheckedValueTo = switchifBlockedByAdminOverrideCheckedValueTo,
restrictionsProviderFactory = restrictionsProviderFactory,
)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
index d2867af1eda6..771eb85ee21a 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
@@ -116,12 +116,15 @@ fun <T : AppRecord> TogglePermissionAppListModel<T>.isChangeableWithSystemUidChe
fun <T : AppRecord> TogglePermissionAppListModel<T>.getRestrictions(
userId: Int,
packageName: String,
+ isRestrictedSettingAllowed: Boolean?
) =
Restrictions(
userId = userId,
keys = switchRestrictionKeys,
enhancedConfirmation =
- enhancedConfirmationKey?.let { key -> EnhancedConfirmation(key, packageName) },
+ enhancedConfirmationKey?.let {
+ key -> EnhancedConfirmation(key, packageName, isRestrictedSettingAllowed)
+ },
)
interface TogglePermissionAppListProvider {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
index ec44d2af4ffa..bef2bdaaefaf 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
@@ -149,13 +149,14 @@ internal class TogglePermissionInternalAppListModel<T : AppRecord>(
@Composable
fun getSummary(record: T): () -> String {
+ val allowed = listModel.isAllowed(record)
val restrictions =
listModel.getRestrictions(
userId = record.app.userId,
packageName = record.app.packageName,
+ allowed()
)
val restrictedMode by restrictionsProviderFactory.rememberRestrictedMode(restrictions)
- val allowed = listModel.isAllowed(record)
return RestrictedSwitchPreferenceModel.getSummary(
context = context,
summaryIfNoRestricted = { getSummaryIfNoRestricted(allowed()) },
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index dbefcd7cf45f..a92df8026715 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -237,6 +237,13 @@ flag {
}
flag {
+ name: "notification_bundle_ui"
+ namespace: "systemui"
+ description: "Three-level group UI for notification bundles"
+ bug: "367996732"
+}
+
+flag {
name: "notification_background_tint_optimization"
namespace: "systemui"
description: "Re-enable the codepath that removed tinting of notifications when the"
@@ -1942,16 +1949,6 @@ flag {
}
flag {
- name: "stabilize_heads_up_group"
- namespace: "systemui"
- description: "Stabilize heads up groups in VisualStabilityCoordinator"
- bug: "381864715"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "magnetic_notification_horizontal_swipe"
namespace: "systemui"
description: "Add support for magnetic behavior on horizontal notification swipes."
@@ -1990,4 +1987,14 @@ flag {
metadata {
purpose: PURPOSE_BUGFIX
}
-} \ No newline at end of file
+}
+
+flag {
+ name: "shade_launch_accessibility"
+ namespace: "systemui"
+ description: "Intercept accessibility focus events for the Shade during launch animations to avoid stray TalkBack events."
+ bug: "379222226"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
index bdd0da9ce4a4..4e10ff689b19 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
@@ -67,11 +67,10 @@ import com.android.systemui.Flags
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.compose.modifiers.sysuiResTag
-import com.android.systemui.haptics.slider.SeekableSliderTrackerConfig
-import com.android.systemui.haptics.slider.SliderHapticFeedbackConfig
import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.res.R
+import com.android.systemui.volume.haptics.ui.VolumeHapticsConfigsProvider
import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderState
import kotlin.math.round
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -103,6 +102,10 @@ fun VolumeSlider(
}
val value by valueState(state)
+ val interactionSource = remember { MutableInteractionSource() }
+ val hapticsViewModel: SliderHapticsViewModel? =
+ setUpHapticsViewModel(value, state.valueRange, interactionSource, hapticsViewModelFactory)
+
Column(modifier = modifier.animateContentSize(), verticalArrangement = Arrangement.Top) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
@@ -127,8 +130,14 @@ fun VolumeSlider(
Slider(
value = value,
valueRange = state.valueRange,
- onValueChange = onValueChange,
- onValueChangeFinished = onValueChangeFinished,
+ onValueChange = { newValue ->
+ hapticsViewModel?.addVelocityDataPoint(newValue)
+ onValueChange(newValue)
+ },
+ onValueChangeFinished = {
+ hapticsViewModel?.onValueChangeEnded()
+ onValueChangeFinished?.invoke()
+ },
enabled = state.isEnabled,
modifier =
Modifier.height(40.dp)
@@ -210,41 +219,8 @@ private fun LegacyVolumeSlider(
) {
val value by valueState(state)
val interactionSource = remember { MutableInteractionSource() }
- val sliderStepSize = 1f / (state.valueRange.endInclusive - state.valueRange.start)
val hapticsViewModel: SliderHapticsViewModel? =
- hapticsViewModelFactory?.let {
- rememberViewModel(traceName = "SliderHapticsViewModel") {
- it.create(
- interactionSource,
- state.valueRange,
- Orientation.Horizontal,
- SliderHapticFeedbackConfig(
- lowerBookendScale = 0.2f,
- progressBasedDragMinScale = 0.2f,
- progressBasedDragMaxScale = 0.5f,
- deltaProgressForDragThreshold = 0f,
- additionalVelocityMaxBump = 0.2f,
- maxVelocityToScale = 0.1f, /* slider progress(from 0 to 1) per sec */
- sliderStepSize = sliderStepSize,
- ),
- SeekableSliderTrackerConfig(
- lowerBookendThreshold = 0f,
- upperBookendThreshold = 1f,
- ),
- )
- }
- }
- var lastDiscreteStep by remember { mutableFloatStateOf(round(value)) }
- LaunchedEffect(value) {
- snapshotFlow { value }
- .map { round(it) }
- .filter { it != lastDiscreteStep }
- .distinctUntilChanged()
- .collect { discreteStep ->
- lastDiscreteStep = discreteStep
- hapticsViewModel?.onValueChange(discreteStep)
- }
- }
+ setUpHapticsViewModel(value, state.valueRange, interactionSource, hapticsViewModelFactory)
PlatformSlider(
modifier =
@@ -357,3 +333,36 @@ private fun SliderIcon(
content = { Icon(modifier = Modifier.size(24.dp), icon = icon) },
)
}
+
+@Composable
+fun setUpHapticsViewModel(
+ value: Float,
+ valueRange: ClosedFloatingPointRange<Float>,
+ interactionSource: MutableInteractionSource,
+ hapticsViewModelFactory: SliderHapticsViewModel.Factory?,
+): SliderHapticsViewModel? {
+ return hapticsViewModelFactory?.let {
+ rememberViewModel(traceName = "SliderHapticsViewModel") {
+ it.create(
+ interactionSource,
+ valueRange,
+ Orientation.Horizontal,
+ VolumeHapticsConfigsProvider.sliderHapticFeedbackConfig(valueRange),
+ VolumeHapticsConfigsProvider.seekableSliderTrackerConfig,
+ )
+ }
+ .also { hapticsViewModel ->
+ var lastDiscreteStep by remember { mutableFloatStateOf(round(value)) }
+ LaunchedEffect(value) {
+ snapshotFlow { value }
+ .map { round(it) }
+ .filter { it != lastDiscreteStep }
+ .distinctUntilChanged()
+ .collect { discreteStep ->
+ lastDiscreteStep = discreteStep
+ hapticsViewModel.onValueChange(discreteStep)
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
index 827bd6898310..67cbf3082632 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
@@ -125,7 +125,19 @@ class FlexClockFaceController(clockCtx: ClockContext, private val isLargeClock:
layerController.faceEvents.onThemeChanged(theme)
}
- override fun onFontAxesChanged(axes: List<ClockFontAxisSetting>) {
+ override fun onFontAxesChanged(settings: List<ClockFontAxisSetting>) {
+ var axes = settings
+ if (!isLargeClock) {
+ axes =
+ axes.map { axis ->
+ if (axis.key == "wdth" && axis.value > SMALL_CLOCK_MAX_WDTH) {
+ axis.copy(value = SMALL_CLOCK_MAX_WDTH)
+ } else {
+ axis
+ }
+ }
+ }
+
layerController.events.onFontAxesChanged(axes)
}
@@ -236,6 +248,7 @@ class FlexClockFaceController(clockCtx: ClockContext, private val isLargeClock:
}
companion object {
+ val SMALL_CLOCK_MAX_WDTH = 120f
val SMALL_LAYER_CONFIG =
LayerConfig(
timespec = DigitalTimespec.TIME_FULL_FORMAT,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/DefaultShortcutCategoriesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/DefaultShortcutCategoriesRepositoryTest.kt
index 3bf59f34db76..cd05980385e0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/DefaultShortcutCategoriesRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/DefaultShortcutCategoriesRepositoryTest.kt
@@ -50,6 +50,7 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
+import com.android.systemui.keyboard.shortcut.shortcutHelperAccessibilityShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperAppCategoriesShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperCurrentAppShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperInputShortcutsSource
@@ -88,6 +89,7 @@ class DefaultShortcutCategoriesRepositoryTest : SysuiTestCase() {
it.shortcutHelperAppCategoriesShortcutsSource = fakeAppCategoriesSource
it.shortcutHelperInputShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperCurrentAppShortcutsSource = FakeKeyboardShortcutGroupsSource()
+ it.shortcutHelperAccessibilityShortcutsSource = FakeKeyboardShortcutGroupsSource()
}
private val repo = kosmos.defaultShortcutCategoriesRepository
@@ -284,14 +286,20 @@ class DefaultShortcutCategoriesRepositoryTest : SysuiTestCase() {
val categories by collectLastValue(repo.categories)
val cycleForwardThroughRecentAppsShortcut =
- categories?.first { it.type == ShortcutCategoryType.MultiTasking }
- ?.subCategories?.first { it.label == recentAppsGroup.label }
- ?.shortcuts?.first { it.label == CYCLE_FORWARD_THROUGH_RECENT_APPS_SHORTCUT_LABEL }
+ categories
+ ?.first { it.type == ShortcutCategoryType.MultiTasking }
+ ?.subCategories
+ ?.first { it.label == recentAppsGroup.label }
+ ?.shortcuts
+ ?.first { it.label == CYCLE_FORWARD_THROUGH_RECENT_APPS_SHORTCUT_LABEL }
val cycleBackThroughRecentAppsShortcut =
- categories?.first { it.type == ShortcutCategoryType.MultiTasking }
- ?.subCategories?.first { it.label == recentAppsGroup.label }
- ?.shortcuts?.first { it.label == CYCLE_BACK_THROUGH_RECENT_APPS_SHORTCUT_LABEL }
+ categories
+ ?.first { it.type == ShortcutCategoryType.MultiTasking }
+ ?.subCategories
+ ?.first { it.label == recentAppsGroup.label }
+ ?.shortcuts
+ ?.first { it.label == CYCLE_BACK_THROUGH_RECENT_APPS_SHORTCUT_LABEL }
assertThat(cycleForwardThroughRecentAppsShortcut?.isCustomizable).isFalse()
assertThat(cycleBackThroughRecentAppsShortcut?.isCustomizable).isFalse()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt
index 8f0bc640f0eb..61490986f4a9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt
@@ -38,6 +38,7 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.InputMethodEditor
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.MultiTasking
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.System
+import com.android.systemui.keyboard.shortcut.shortcutHelperAccessibilityShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperAppCategoriesShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperCategoriesInteractor
import com.android.systemui.keyboard.shortcut.shortcutHelperCurrentAppShortcutsSource
@@ -76,6 +77,7 @@ class ShortcutHelperCategoriesInteractorTest : SysuiTestCase() {
it.shortcutHelperMultiTaskingShortcutsSource = multitaskingShortcutsSource
it.shortcutHelperAppCategoriesShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperCurrentAppShortcutsSource = FakeKeyboardShortcutGroupsSource()
+ it.shortcutHelperAccessibilityShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { mockUserContext })
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt
index 000024f9b814..7a343351ef64 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperDialogStarterTest.kt
@@ -26,6 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.keyboard.shortcut.data.source.FakeKeyboardShortcutGroupsSource
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts
import com.android.systemui.keyboard.shortcut.shortcutCustomizationDialogStarterFactory
+import com.android.systemui.keyboard.shortcut.shortcutHelperAccessibilityShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperAppCategoriesShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperCurrentAppShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperInputShortcutsSource
@@ -66,6 +67,7 @@ class ShortcutHelperDialogStarterTest : SysuiTestCase() {
it.testDispatcher = UnconfinedTestDispatcher()
it.shortcutHelperSystemShortcutsSource = fakeSystemSource
it.shortcutHelperMultiTaskingShortcutsSource = fakeMultiTaskingSource
+ it.shortcutHelperAccessibilityShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperAppCategoriesShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperInputShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperCurrentAppShortcutsSource = FakeKeyboardShortcutGroupsSource()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
index 3fc46b973959..cf38072912e9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
@@ -45,6 +45,7 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.System
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import com.android.systemui.keyboard.shortcut.shared.model.shortcut
+import com.android.systemui.keyboard.shortcut.shortcutHelperAccessibilityShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperAppCategoriesShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperCurrentAppShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperInputShortcutsSource
@@ -95,6 +96,7 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
it.shortcutHelperMultiTaskingShortcutsSource = fakeMultiTaskingSource
it.shortcutHelperAppCategoriesShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperInputShortcutsSource = FakeKeyboardShortcutGroupsSource()
+ it.shortcutHelperAccessibilityShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperCurrentAppShortcutsSource = fakeCurrentAppsSource
it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { mockUserContext })
}
@@ -112,9 +114,12 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
fakeSystemSource.setGroups(TestShortcuts.systemGroups)
fakeMultiTaskingSource.setGroups(TestShortcuts.multitaskingGroups)
fakeCurrentAppsSource.setGroups(TestShortcuts.currentAppGroups)
- whenever(mockPackageManager.getApplicationInfo(anyString(), eq(0))).thenReturn(mockApplicationInfo)
- whenever(mockPackageManager.getApplicationLabel(mockApplicationInfo)).thenReturn("Current App")
- whenever(mockPackageManager.getApplicationIcon(anyString())).thenThrow(NameNotFoundException())
+ whenever(mockPackageManager.getApplicationInfo(anyString(), eq(0)))
+ .thenReturn(mockApplicationInfo)
+ whenever(mockPackageManager.getApplicationLabel(mockApplicationInfo))
+ .thenReturn("Current App")
+ whenever(mockPackageManager.getApplicationIcon(anyString()))
+ .thenThrow(NameNotFoundException())
whenever(mockUserContext.packageManager).thenReturn(mockPackageManager)
whenever(mockUserContext.getSystemService(INPUT_SERVICE)).thenReturn(inputManager)
}
@@ -278,11 +283,11 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
fun shortcutsUiState_currentAppIsLauncher_defaultSelectedCategoryIsSystem() =
testScope.runTest {
whenever(
- mockRoleManager.getRoleHoldersAsUser(
- RoleManager.ROLE_HOME,
- fakeUserTracker.userHandle,
+ mockRoleManager.getRoleHoldersAsUser(
+ RoleManager.ROLE_HOME,
+ fakeUserTracker.userHandle,
+ )
)
- )
.thenReturn(listOf(TestShortcuts.currentAppPackageName))
val uiState by collectLastValue(viewModel.shortcutsUiState)
@@ -318,23 +323,23 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
label = "System",
iconSource = IconSource(imageVector = Icons.Default.Tv),
shortcutCategory =
- ShortcutCategory(
- System,
- subCategoryWithShortcutLabels("first Foo shortcut1"),
- subCategoryWithShortcutLabels(
- "second foO shortcut2",
- subCategoryLabel = SECOND_SIMPLE_GROUP_LABEL,
+ ShortcutCategory(
+ System,
+ subCategoryWithShortcutLabels("first Foo shortcut1"),
+ subCategoryWithShortcutLabels(
+ "second foO shortcut2",
+ subCategoryLabel = SECOND_SIMPLE_GROUP_LABEL,
+ ),
),
- ),
),
ShortcutCategoryUi(
label = "Multitasking",
iconSource = IconSource(imageVector = Icons.Default.VerticalSplit),
shortcutCategory =
- ShortcutCategory(
- MultiTasking,
- subCategoryWithShortcutLabels("third FoO shortcut1"),
- ),
+ ShortcutCategory(
+ MultiTasking,
+ subCategoryWithShortcutLabels("third FoO shortcut1"),
+ ),
),
)
}
@@ -420,9 +425,8 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
@Test
fun shortcutsUiState_shouldShowResetButton_isTrueWhenThereAreCustomShortcuts() =
testScope.runTest {
- whenever(
- inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
- ).thenReturn(listOf(allAppsInputGestureData))
+ whenever(inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY))
+ .thenReturn(listOf(allAppsInputGestureData))
val uiState by collectLastValue(viewModel.shortcutsUiState)
testHelper.showFromActivity()
@@ -433,7 +437,7 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
@Test
fun shortcutsUiState_searchQuery_isResetAfterHelperIsClosedAndReOpened() =
- testScope.runTest{
+ testScope.runTest {
val uiState by collectLastValue(viewModel.shortcutsUiState)
openHelperAndSearchForFooString()
@@ -443,7 +447,7 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
assertThat((uiState as? ShortcutsUiState.Active)?.searchQuery).isEqualTo("")
}
- private fun openHelperAndSearchForFooString(){
+ private fun openHelperAndSearchForFooString() {
testHelper.showFromActivity()
viewModel.onSearchQueryChanged("foo")
}
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 83b821619659..286f8bfd63a2 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
@@ -123,8 +123,8 @@ class AlternateBouncerToPrimaryBouncerTransitionViewModelTest : SysuiTestCase()
kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
transitionProgress = listOf(0f, 0f, 0.1f, 0.2f, 0.3f, 1f),
- startValue = kosmos.blurConfig.maxBlurRadiusPx / 3.0f,
- endValue = kosmos.blurConfig.maxBlurRadiusPx / 3.0f,
+ startValue = kosmos.blurConfig.maxBlurRadiusPx,
+ endValue = kosmos.blurConfig.maxBlurRadiusPx,
transitionFactory = ::step,
actualValuesProvider = { values },
checkInterpolatedValues = false,
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 fdee8d0544f0..60a19a4c7d07 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
@@ -198,8 +198,8 @@ class LockscreenToPrimaryBouncerTransitionViewModelTest(flags: FlagsParameteriza
kosmos.keyguardWindowBlurTestUtil.assertTransitionToBlurRadius(
transitionProgress = listOf(0f, 0f, 0.1f, 0.2f, 0.3f, 1f),
- startValue = kosmos.blurConfig.maxBlurRadiusPx / 3.0f,
- endValue = kosmos.blurConfig.maxBlurRadiusPx / 3.0f,
+ startValue = kosmos.blurConfig.maxBlurRadiusPx,
+ endValue = kosmos.blurConfig.maxBlurRadiusPx,
transitionFactory = ::step,
actualValuesProvider = { values },
checkInterpolatedValues = false,
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 7f9313cbeb5b..83b68fed768e 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
@@ -18,7 +18,7 @@ package com.android.systemui.navigationbar.views;
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING;
import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
import static android.inputmethodservice.InputMethodService.IME_VISIBLE;
@@ -32,7 +32,7 @@ import static com.android.systemui.navigationbar.views.NavigationBar.NavBarActio
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_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.google.common.truth.Truth.assertThat;
@@ -501,7 +501,7 @@ public class NavigationBarTest extends SysuiTestCase {
mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SHOWING), eq(true));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_SHOWING), eq(true));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING), eq(true));
}
/**
@@ -515,7 +515,7 @@ public class NavigationBarTest extends SysuiTestCase {
mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, false /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SHOWING), eq(true));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_SHOWING), eq(false));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING), eq(false));
}
/**
@@ -532,7 +532,7 @@ public class NavigationBarTest extends SysuiTestCase {
mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, 0 /* vis */,
BACK_DISPOSITION_DEFAULT, true /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SHOWING), eq(false));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_SHOWING), eq(false));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING), eq(false));
}
/**
@@ -546,7 +546,7 @@ public class NavigationBarTest extends SysuiTestCase {
mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, IME_VISIBLE,
BACK_DISPOSITION_ADJUST_NOTHING, true /* showImeSwitcher */);
verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SHOWING), eq(true));
- verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_SHOWING), eq(true));
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING), eq(true));
}
@Test
@@ -568,12 +568,12 @@ public class NavigationBarTest extends SysuiTestCase {
// Verify IME window state will be updated in default NavBar & external NavBar state reset.
assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN
- | NAVIGATION_HINT_IME_SWITCHER_SHOWN,
+ | NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN,
defaultNavBar.getNavigationIconHints());
assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
- assertFalse((externalNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SWITCHER_SHOWN)
- != 0);
+ assertFalse((externalNavBar.getNavigationIconHints()
+ & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0);
externalNavBar.setImeWindowStatus(EXTERNAL_DISPLAY_ID, IME_VISIBLE,
BACK_DISPOSITION_DEFAULT, true);
@@ -581,12 +581,12 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_DEFAULT, false);
// Verify IME window state will be updated in external NavBar & default NavBar state reset.
assertEquals(NAVIGATION_HINT_BACK_ALT | NAVIGATION_HINT_IME_SHOWN
- | NAVIGATION_HINT_IME_SWITCHER_SHOWN,
+ | NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN,
externalNavBar.getNavigationIconHints());
assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
- assertFalse((defaultNavBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SWITCHER_SHOWN)
- != 0);
+ assertFalse((defaultNavBar.getNavigationIconHints()
+ & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0);
}
@Test
@@ -604,8 +604,8 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_DEFAULT, true);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
- assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SWITCHER_SHOWN)
- != 0);
+ assertTrue((mNavigationBar.getNavigationIconHints()
+ & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0);
// Verify navbar didn't alter and showing back icon when the keyguard is showing without
// requesting IME insets visible.
@@ -614,8 +614,8 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_DEFAULT, true);
assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
- assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SWITCHER_SHOWN)
- != 0);
+ assertFalse((mNavigationBar.getNavigationIconHints()
+ & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0);
// Verify navbar altered and showing back icon when the keyguard is showing and
// requesting IME insets visible.
@@ -625,8 +625,8 @@ public class NavigationBarTest extends SysuiTestCase {
BACK_DISPOSITION_DEFAULT, true);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
- assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SWITCHER_SHOWN)
- != 0);
+ assertTrue((mNavigationBar.getNavigationIconHints()
+ & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0);
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ModesTileTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
index f005375a2ef9..7bb28dbabd5e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ModesTileTest.kt
@@ -49,6 +49,7 @@ import com.android.systemui.statusbar.policy.data.repository.zenModeRepository
import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate
import com.android.systemui.statusbar.policy.ui.dialog.modesDialogEventLogger
+import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.modesDialogViewModel
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.settings.FakeSettings
@@ -146,6 +147,7 @@ class ModesTileTest : SysuiTestCase() {
tileDataInteractor,
mapper,
userActionInteractor,
+ kosmos.modesDialogViewModel,
)
underTest.initialize()
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 ee9cb141a700..555c717e1e65 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -20,7 +20,7 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper.RunWithLooper
import android.view.Choreographer
-import android.view.MotionEvent
+import android.view.accessibility.AccessibilityEvent
import android.widget.FrameLayout
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -45,7 +45,10 @@ import com.android.systemui.res.R
import com.android.systemui.settings.brightness.data.repository.BrightnessMirrorShowingRepository
import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
+import com.android.systemui.shade.data.repository.ShadeAnimationRepository
+import com.android.systemui.shade.data.repository.ShadeRepositoryImpl
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.statusbar.DragDownHelper
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -185,6 +188,10 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
notificationShadeDepthController,
underTest,
shadeViewController,
+ ShadeAnimationInteractorLegacyImpl(
+ ShadeAnimationRepository(),
+ ShadeRepositoryImpl(testScope),
+ ),
panelExpansionInteractor,
ShadeExpansionStateManager(),
notificationStackScrollLayoutController,
@@ -259,6 +266,20 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
verify(configurationForwarder).dispatchOnMovedToDisplay(eq(1), eq(config))
}
+ @Test
+ @EnableFlags(AConfigFlags.FLAG_SHADE_LAUNCH_ACCESSIBILITY)
+ fun requestSendAccessibilityEvent_duringLaunchAnimation_blocksFocusEvent() {
+ underTest.setAnimatingContentLaunch(true)
+
+ assertThat(
+ underTest.requestSendAccessibilityEvent(
+ underTest.getChildAt(0),
+ AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED),
+ )
+ )
+ .isFalse()
+ }
+
private fun captureInteractionEventHandler() {
verify(underTest).setInteractionEventHandler(interactionEventHandlerCaptor.capture())
interactionEventHandler = interactionEventHandlerCaptor.value
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt
index 22906b8724b5..c515d940d2aa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt
@@ -144,7 +144,8 @@ class TargetSdkResolverTest : SysuiTestCase() {
/* rankingAdjustment = */ 0,
/* isBubble = */ false,
/* proposedImportance = */ 0,
- /* sensitiveContent = */ false
+ /* sensitiveContent = */ false,
+ /* summarization = */ null
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index 7b120947b1d6..2aa1efaa429f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -107,7 +107,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
return SceneContainerFlagParameterizationKt
- .andSceneContainer(allCombinationsOf(Flags.FLAG_STABILIZE_HEADS_UP_GROUP));
+ .andSceneContainer(allCombinationsOf(Flags.FLAG_STABILIZE_HEADS_UP_GROUP_V2));
}
private VisualStabilityCoordinator mCoordinator;
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index aa48c29de028..99cdf731a765 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -265,7 +265,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
userRestrictionChecker = mock(),
- processWrapper = ProcessWrapperFake(activityManager)
+ processWrapper = ProcessWrapperFake()
)
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index bcf964fa6832..917df619467d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -177,7 +177,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
userRestrictionChecker = mock(),
- processWrapper = ProcessWrapperFake(activityManager)
+ processWrapper = ProcessWrapperFake()
),
guestUserInteractor = guestUserInteractor,
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractorTest.kt
index 799ca4a49038..0a50722d8fed 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractorTest.kt
@@ -18,7 +18,6 @@ package com.android.systemui.volume.dialog.sliders.domain.interactor
import android.app.ActivityManager
import android.testing.TestableLooper
-import android.view.MotionEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -29,6 +28,7 @@ import com.android.systemui.testKosmos
import com.android.systemui.volume.Events
import com.android.systemui.volume.dialog.domain.interactor.volumeDialogVisibilityInteractor
import com.android.systemui.volume.dialog.shared.model.VolumeDialogVisibilityModel
+import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.time.Duration.Companion.seconds
@@ -73,16 +73,7 @@ class VolumeDialogSliderInputEventsInteractorTest : SysuiTestCase() {
assertThat(dialogVisibility)
.isInstanceOf(VolumeDialogVisibilityModel.Visible::class.java)
- underTest.onTouchEvent(
- MotionEvent.obtain(
- /* downTime = */ 0,
- /* eventTime = */ 0,
- /* action = */ 0,
- /* x = */ 0f,
- /* y = */ 0f,
- /* metaState = */ 0,
- )
- )
+ underTest.onTouchEvent(SliderInputEvent.Touch.Start(0f, 0f))
advanceTimeBy(volumeDialogTimeout / 2)
assertThat(dialogVisibility)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
index 2985053f56d5..d6343c840d9b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
@@ -26,4 +26,5 @@ class FakeWallpaperRepository : WallpaperRepository {
override val wallpaperInfo = MutableStateFlow<WallpaperInfo?>(null)
override val wallpaperSupportsAmbientMode = flowOf(false)
override var rootView: View? = null
+ override val shouldSendFocalArea = MutableStateFlow(false)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
index 03753d9aa884..115edd0d3bb0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
@@ -67,7 +67,6 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
fakeBroadcastDispatcher,
userRepository,
keyguardRepository,
- keyguardClockRepository,
wallpaperManager,
context,
)
@@ -252,7 +251,7 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
@EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
fun shouldSendNotificationLayout_setMagicPortraitWallpaper_launchSendLayoutJob() =
testScope.runTest {
- val latest by collectLastValue(underTest.shouldSendNotificationLayout)
+ val latest by collectLastValue(underTest.shouldSendFocalArea)
val magicPortraitWallpaper =
mock<WallpaperInfo>().apply {
whenever(this.component)
@@ -273,7 +272,7 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
@EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
fun shouldSendNotificationLayout_setNotMagicPortraitWallpaper_cancelSendLayoutJob() =
testScope.runTest {
- val latest by collectLastValue(underTest.shouldSendNotificationLayout)
+ val latest by collectLastValue(underTest.shouldSendFocalArea)
val magicPortraitWallpaper = MAGIC_PORTRAIT_WP
whenever(wallpaperManager.getWallpaperInfoForUser(any()))
.thenReturn(magicPortraitWallpaper)
diff --git a/packages/SystemUI/res/layout/volume_dialog_slider.xml b/packages/SystemUI/res/layout/volume_dialog_slider.xml
index c5f468e731f5..2628f4991b49 100644
--- a/packages/SystemUI/res/layout/volume_dialog_slider.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_slider.xml
@@ -18,14 +18,10 @@
android:layout_height="match_parent"
android:maxHeight="@dimen/volume_dialog_slider_height">
- <com.google.android.material.slider.Slider
+ <androidx.compose.ui.platform.ComposeView
android:id="@+id/volume_dialog_slider"
- style="@style/SystemUI.Material3.Slider.Volume"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
- android:layout_marginTop="-20dp"
- android:layout_marginBottom="-20dp"
- android:orientation="vertical"
- android:theme="@style/Theme.Material3.DayNight" />
+ android:orientation="vertical" />
</FrameLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-xlarge-land/config.xml b/packages/SystemUI/res/values-xlarge-land/config.xml
index 5e4304e1c13a..6d8b64ade259 100644
--- a/packages/SystemUI/res/values-xlarge-land/config.xml
+++ b/packages/SystemUI/res/values-xlarge-land/config.xml
@@ -16,4 +16,5 @@
<resources>
<item name="shortcut_helper_screen_width_fraction" format="float" type="dimen">0.8</item>
+ <bool name="center_align_magic_portrait_shape">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 940e87d3d163..68e33f27aefa 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -1104,7 +1104,10 @@
-->
<bool name="config_userSwitchingMustGoThroughLoginScreen">false</bool>
-
<!-- The dream component used when the device is low light environment. -->
<string translatable="false" name="config_lowLightDreamComponent"/>
+
+ <!--Whether we should position magic portrait shape effects in the center of lockscreen
+ it's false by default, and only be true in tablet landscape -->
+ <bool name="center_align_magic_portrait_shape">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b572a8062e6e..64367ef79856 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2316,9 +2316,6 @@
<string name="group_system_lock_screen">Lock screen</string>
<!-- User visible title for the keyboard shortcut that pulls up Notes app for quick memo. [CHAR LIMIT=70] -->
<string name="group_system_quick_memo">Take a note</string>
- <!-- TODO(b/383734125): make it translatable once string is finalized by UXW.-->
- <!-- User visible title for the keyboard shortcut that toggles Voice Access. [CHAR LIMIT=70] -->
- <string name="group_system_toggle_voice_access" translatable="false">Toggle Voice Access</string>
<!-- User visible title for the multitasking keyboard shortcuts list. [CHAR LIMIT=70] -->
<string name="keyboard_shortcut_group_system_multitasking">Multitasking</string>
@@ -2377,6 +2374,17 @@
<!-- User visible title for the keyboard shortcut that takes the user to the maps app. [CHAR LIMIT=70] -->
<string name="keyboard_shortcut_group_applications_maps">Maps</string>
+ <!-- User visible title for the keyboard shortcut that toggles bounce keys. [CHAR LIMIT=70]-->
+ <string name="group_accessibility_toggle_bounce_keys">Toggle bounce keys</string>
+ <!-- User visible title for the keyboard shortcut that toggles mouse keys. [CHAR LIMIT=70]-->
+ <string name="group_accessibility_toggle_mouse_keys">Toggle mouse keys</string>
+ <!-- User visible title for the keyboard shortcut that toggles sticky keys. [CHAR LIMIT=70]-->
+ <string name="group_accessibility_toggle_sticky_keys">Toggle sticky keys</string>
+ <!-- User visible title for the keyboard shortcut that toggles slow keys. [CHAR LIMIT=70]-->
+ <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>
+
<!-- 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 b0d9bed05e27..c95c6dd89353 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -565,16 +565,6 @@
<item name="android:windowNoTitle">true</item>
</style>
- <style name="SystemUI.Material3.Slider.Volume">
- <item name="trackHeight">40dp</item>
- <item name="thumbHeight">52dp</item>
- <item name="trackCornerSize">12dp</item>
- <item name="trackInsideCornerSize">2dp</item>
- <item name="trackStopIndicatorSize">6dp</item>
- <item name="trackIconSize">20dp</item>
- <item name="labelBehavior">gone</item>
- </style>
-
<style name="SystemUI.Material3.Slider" parent="@style/Widget.Material3.Slider">
<item name="labelStyle">@style/Widget.Material3.Slider.Label</item>
<item name="thumbColor">@color/thumb_color</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index 8576a6ebac42..a518c57bdd16 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -72,6 +72,25 @@ public class Task {
@ViewDebug.ExportedProperty(category = "recents")
public final int displayId;
+ /**
+ * The component of the first activity in the task, can be considered the "application" of
+ * this task.
+ */
+ @Nullable
+ public ComponentName baseActivity;
+ /**
+ * The number of activities in this task (including running).
+ */
+ public int numActivities;
+ /**
+ * Whether the top activity is to be displayed. See {@link android.R.attr#windowNoDisplay}.
+ */
+ public boolean isTopActivityNoDisplay;
+ /**
+ * Whether fillsParent() is false for every activity in the tasks stack.
+ */
+ public boolean isActivityStackTransparent;
+
// The source component name which started this task
public final ComponentName sourceComponent;
@@ -90,6 +109,10 @@ public class Task {
this.userId = t.userId;
this.lastActiveTime = t.lastActiveTime;
this.displayId = t.displayId;
+ this.baseActivity = t.baseActivity;
+ this.numActivities = t.numActivities;
+ this.isTopActivityNoDisplay = t.isTopActivityNoDisplay;
+ this.isActivityStackTransparent = t.isActivityStackTransparent;
updateHashCode();
}
@@ -106,7 +129,9 @@ public class Task {
}
public TaskKey(int id, int windowingMode, @NonNull Intent intent,
- ComponentName sourceComponent, int userId, long lastActiveTime, int displayId) {
+ ComponentName sourceComponent, int userId, long lastActiveTime, int displayId,
+ @Nullable ComponentName baseActivity, int numActivities,
+ boolean isTopActivityNoDisplay, boolean isActivityStackTransparent) {
this.id = id;
this.windowingMode = windowingMode;
this.baseIntent = intent;
@@ -114,6 +139,10 @@ public class Task {
this.userId = userId;
this.lastActiveTime = lastActiveTime;
this.displayId = displayId;
+ this.baseActivity = baseActivity;
+ this.numActivities = numActivities;
+ this.isTopActivityNoDisplay = isTopActivityNoDisplay;
+ this.isActivityStackTransparent = isActivityStackTransparent;
updateHashCode();
}
@@ -185,6 +214,10 @@ public class Task {
parcel.writeLong(lastActiveTime);
parcel.writeInt(displayId);
parcel.writeTypedObject(sourceComponent, flags);
+ parcel.writeTypedObject(baseActivity, flags);
+ parcel.writeInt(numActivities);
+ parcel.writeBoolean(isTopActivityNoDisplay);
+ parcel.writeBoolean(isActivityStackTransparent);
}
private static TaskKey readFromParcel(Parcel parcel) {
@@ -195,9 +228,14 @@ public class Task {
long lastActiveTime = parcel.readLong();
int displayId = parcel.readInt();
ComponentName sourceComponent = parcel.readTypedObject(ComponentName.CREATOR);
+ ComponentName baseActivity = parcel.readTypedObject(ComponentName.CREATOR);
+ int numActivities = parcel.readInt();
+ boolean isTopActivityNoDisplay = parcel.readBoolean();
+ boolean isActivityStackTransparent = parcel.readBoolean();
return new TaskKey(id, windowingMode, baseIntent, sourceComponent, userId,
- lastActiveTime, displayId);
+ lastActiveTime, displayId, baseActivity, numActivities, isTopActivityNoDisplay,
+ isActivityStackTransparent);
}
@Override
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 41ad4373455e..818e39800b0c 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
@@ -18,9 +18,10 @@ package com.android.systemui.shared.recents.utilities;
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
import android.annotation.TargetApi;
+import android.app.StatusBarManager.NavigationHint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
@@ -103,10 +104,15 @@ public class Utilities {
}
/**
- * @return updated set of flags from InputMethodService based off {@param oldHints}
- * Leaves original hints unmodified
+ * Gets the updated navigation icon hints, based on the current ones and the given IME state.
+ *
+ * @param oldHints current navigation icon hints.
+ * @param backDisposition the IME back disposition mode.
+ * @param imeShown whether the IME is currently visible.
+ * @param showImeSwitcher whether the IME Switcher button should be shown.
*/
- public static int calculateBackDispositionHints(int oldHints,
+ @NavigationHint
+ public static int calculateNavigationIconHints(@NavigationHint int oldHints,
@BackDispositionMode int backDisposition, boolean imeShown, boolean showImeSwitcher) {
int hints = oldHints;
switch (backDisposition) {
@@ -129,9 +135,9 @@ public class Utilities {
hints &= ~NAVIGATION_HINT_IME_SHOWN;
}
if (showImeSwitcher) {
- hints |= NAVIGATION_HINT_IME_SWITCHER_SHOWN;
+ hints |= NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
} else {
- hints &= ~NAVIGATION_HINT_IME_SWITCHER_SHOWN;
+ hints &= ~NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
}
return hints;
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 6f13d637d5c5..f87d9b05d795 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
@@ -98,12 +98,12 @@ public class QuickStepContract {
public static final long SYSUI_STATE_ONE_HANDED_ACTIVE = 1L << 16;
// Allow system gesture no matter the system bar(s) is visible or not
public static final long SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1L << 17;
- // The IME is showing
+ // The IME is visible.
public static final long SYSUI_STATE_IME_SHOWING = 1L << 18;
// The window magnification is overlapped with system gesture insets at the bottom.
public static final long SYSUI_STATE_MAGNIFICATION_OVERLAP = 1L << 19;
- // ImeSwitcher is showing
- public static final long SYSUI_STATE_IME_SWITCHER_SHOWING = 1L << 20;
+ // The IME Switcher button is visible.
+ public static final long SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING = 1L << 20;
// Device dozing/AOD state
public static final long SYSUI_STATE_DEVICE_DOZING = 1L << 21;
// The home feature is disabled (either by SUW/SysUI/device policy)
@@ -170,7 +170,7 @@ public class QuickStepContract {
SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
SYSUI_STATE_IME_SHOWING,
SYSUI_STATE_MAGNIFICATION_OVERLAP,
- SYSUI_STATE_IME_SWITCHER_SHOWING,
+ SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING,
SYSUI_STATE_DEVICE_DOZING,
SYSUI_STATE_BACK_DISABLED,
SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED,
@@ -250,8 +250,8 @@ public class QuickStepContract {
if ((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0) {
str.add("magnification_overlap");
}
- if ((flags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0) {
- str.add("ime_switcher_showing");
+ if ((flags & SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING) != 0) {
+ str.add("ime_switcher_button_visible");
}
if ((flags & SYSUI_STATE_DEVICE_DOZING) != 0) {
str.add("device_dozing");
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index ae282c7e14bd..e2ac6a494020 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -22,6 +22,7 @@ import android.text.TextUtils;
import android.text.method.SingleLineTransformationMethod;
import android.util.AttributeSet;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.TextView;
import com.android.systemui.res.R;
@@ -65,6 +66,14 @@ public class CarrierText extends TextView {
}
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ // Clear selected state set by CarrierTextController so "selected" not announced by
+ // accessibility but we can still marquee.
+ info.setSelected(false);
+ }
+
public boolean getShowAirplaneMode() {
return mShowAirplaneMode;
}
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 6a42cdc876ca..8e4c9349c604 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
@@ -39,10 +39,14 @@ import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFO
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT
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_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_VOICE_ACCESS
-import com.android.hardware.input.Flags.enableVoiceAccessKeyGestures
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.Accessibility
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.AppCategories
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.MultiTasking
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.System
@@ -65,7 +69,6 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_LAUNCH_ASSISTANT to System,
KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT to System,
KEY_GESTURE_TYPE_ALL_APPS to System,
- KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS to System,
// Multitasking Category
KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER to MultiTasking,
@@ -82,6 +85,13 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
// App Category
KEY_GESTURE_TYPE_LAUNCH_APPLICATION to AppCategories,
+
+ // Accessibility Category
+ KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS to Accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS to Accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS to Accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS to Accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS to Accessibility,
)
val gestureToInternalKeyboardShortcutGroupLabelResIdMap =
@@ -103,7 +113,6 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_LAUNCH_ASSISTANT to R.string.shortcut_helper_category_system_apps,
KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT to
R.string.shortcut_helper_category_system_apps,
- KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS to R.string.shortcut_helper_category_system_apps,
// Multitasking Category
KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT to
@@ -128,6 +137,13 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
// App Category
KEY_GESTURE_TYPE_LAUNCH_APPLICATION to R.string.keyboard_shortcut_group_applications,
+
+ // Accessibility Category
+ KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS to R.string.shortcutHelper_category_accessibility,
+ KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS to R.string.shortcutHelper_category_accessibility,
+ 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,
)
/**
@@ -152,7 +168,6 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_LAUNCH_ASSISTANT to R.string.group_system_access_google_assistant,
KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT to
R.string.group_system_access_google_assistant,
- KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS to R.string.group_system_toggle_voice_access,
// Multitasking Category
KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER to R.string.group_system_cycle_forward,
@@ -169,6 +184,14 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
R.string.system_desktop_mode_toggle_maximize_window,
KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY to
R.string.system_multitasking_move_to_next_display,
+
+ // Accessibility Category
+ KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS to R.string.group_accessibility_toggle_bounce_keys,
+ KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS to R.string.group_accessibility_toggle_mouse_keys,
+ KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS to R.string.group_accessibility_toggle_sticky_keys,
+ 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,
)
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 d92c45591522..0c98f81e7cef 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
@@ -17,9 +17,20 @@
package com.android.systemui.keyboard.shortcut.data.source
import android.content.res.Resources
+import android.hardware.input.InputSettings
+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_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.enableVoiceAccessKeyGestures
+import com.android.hardware.input.Flags.keyboardA11yShortcutControl
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyboard.shortcut.data.model.shortcutInfo
import com.android.systemui.res.R
import javax.inject.Inject
@@ -33,5 +44,68 @@ class AccessibilityShortcutsSource @Inject constructor(@Main private val resourc
)
)
- private fun accessibilityShortcuts() = listOf<KeyboardShortcutInfo>()
+ private fun accessibilityShortcuts(): List<KeyboardShortcutInfo> {
+ val shortcuts = mutableListOf<KeyboardShortcutInfo>()
+
+ if (keyboardA11yShortcutControl()) {
+ if (InputSettings.isAccessibilityBounceKeysFeatureEnabled()) {
+ shortcuts.add(
+ // Toggle bounce keys:
+ // - Meta + Alt + 3
+ shortcutInfo(
+ resources.getString(R.string.group_accessibility_toggle_bounce_keys)
+ ) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_3)
+ }
+ )
+ }
+ if (InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled()) {
+ shortcuts.add(
+ // Toggle mouse keys:
+ // - Meta + Alt + 4
+ shortcutInfo(
+ resources.getString(R.string.group_accessibility_toggle_mouse_keys)
+ ) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_4)
+ }
+ )
+ }
+ if (InputSettings.isAccessibilityStickyKeysFeatureEnabled()) {
+ shortcuts.add(
+ // Toggle sticky keys:
+ // - Meta + Alt + 5
+ shortcutInfo(
+ resources.getString(R.string.group_accessibility_toggle_sticky_keys)
+ ) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_5)
+ }
+ )
+ }
+ if (InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled()) {
+ shortcuts.add(
+ // Toggle slow keys:
+ // - Meta + Alt + 6
+ shortcutInfo(
+ resources.getString(R.string.group_accessibility_toggle_slow_keys)
+ ) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_6)
+ }
+ )
+ }
+ }
+
+ if (enableVoiceAccessKeyGestures()) {
+ shortcuts.add(
+ // Toggle voice access:
+ // - Meta + Alt + V
+ shortcutInfo(
+ resources.getString(R.string.group_accessibility_toggle_voice_access)
+ ) {
+ command(META_META_ON or META_ALT_ON, KEYCODE_V)
+ }
+ )
+ }
+
+ 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 c3c9df97a682..5060abdda247 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
@@ -32,14 +32,12 @@ import android.view.KeyEvent.KEYCODE_RECENT_APPS
import android.view.KeyEvent.KEYCODE_S
import android.view.KeyEvent.KEYCODE_SLASH
import android.view.KeyEvent.KEYCODE_TAB
-import android.view.KeyEvent.KEYCODE_V
import android.view.KeyEvent.META_ALT_ON
import android.view.KeyEvent.META_CTRL_ON
import android.view.KeyEvent.META_META_ON
import android.view.KeyEvent.META_SHIFT_ON
import android.view.KeyboardShortcutGroup
import android.view.KeyboardShortcutInfo
-import com.android.hardware.input.Flags.enableVoiceAccessKeyGestures
import com.android.systemui.Flags.shortcutHelperKeyGlyph
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyboard.shortcut.data.model.shortcutInfo
@@ -120,8 +118,8 @@ constructor(@Main private val resources: Resources, private val inputManager: In
return shortcuts
}
- private fun systemControlsShortcuts(): List<KeyboardShortcutInfo> {
- val shortcuts = mutableListOf(
+ private fun systemControlsShortcuts() =
+ listOf(
// Access list of all apps and search (i.e. Search/Launcher):
// - Meta
shortcutInfo(resources.getString(R.string.group_system_access_all_apps_search)) {
@@ -178,19 +176,6 @@ constructor(@Main private val resources: Resources, private val inputManager: In
},
)
- if (enableVoiceAccessKeyGestures()) {
- shortcuts.add(
- // Toggle voice access:
- // - Meta + Alt + V
- shortcutInfo(resources.getString(R.string.group_system_toggle_voice_access)) {
- command(META_META_ON or META_ALT_ON, KEYCODE_V)
- }
- )
- }
-
- return shortcuts
- }
-
private fun systemAppsShortcuts() =
listOf(
// Pull up Notes app for quick memo:
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index 5e0768a2fd24..f37e7685f21c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -27,6 +27,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
+import com.android.systemui.keyguard.domain.interactor.WallpaperFocalAreaInteractor
import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder
import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder
@@ -79,6 +80,7 @@ constructor(
private val keyguardClockViewModel: KeyguardClockViewModel,
private val smartspaceViewModel: KeyguardSmartspaceViewModel,
private val clockInteractor: KeyguardClockInteractor,
+ private val wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor,
private val keyguardViewMediator: KeyguardViewMediator,
private val deviceEntryUnlockTrackerViewBinder: Optional<DeviceEntryUnlockTrackerViewBinder>,
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
@@ -139,6 +141,7 @@ constructor(
screenOffAnimationController,
shadeInteractor,
clockInteractor,
+ wallpaperFocalAreaInteractor,
keyguardClockViewModel,
interactionJankMonitor,
deviceEntryHapticsInteractor,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index cfac965ebb1b..5baef915ea01 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -3594,13 +3594,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// windows that appear on top, ever
int flags = StatusBarManager.DISABLE_NONE;
- // TODO(b/155663717): After restart, status bar will not properly hide home button
+ // TODO (b/155663717) After restart, status bar will not properly hide home button
// unless disable is called to show un-hide it once first
if (forceClearFlags) {
if (UserManager.isVisibleBackgroundUsersEnabled()
- && !mProcessWrapper.isSystemUser()
- && !mProcessWrapper.isForegroundUserOrProfile()) {
- // TODO(b/341604160): Support visible background users properly.
+ && !mProcessWrapper.isSystemUser() && !mProcessWrapper.isForegroundUser()) {
+ // TODO: b/341604160 - Support visible background users properly.
if (DEBUG) {
Log.d(TAG, "Status bar manager is disabled for visible background users");
}
@@ -3636,9 +3635,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
if (!SceneContainerFlag.isEnabled()) {
if (UserManager.isVisibleBackgroundUsersEnabled()
- && !mProcessWrapper.isSystemUser()
- && !mProcessWrapper.isForegroundUserOrProfile()) {
- // TODO(b/341604160): Support visible background users properly.
+ && !mProcessWrapper.isSystemUser() && !mProcessWrapper.isForegroundUser()) {
+ // TODO: b/341604160 - Support visible background users properly.
if (DEBUG) {
Log.d(TAG, "Status bar manager is disabled for visible background users");
}
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 a39982dd31e7..11477fb6cad1 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
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data.repository
import android.graphics.Point
+import android.graphics.RectF
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.widget.LockPatternUtils
import com.android.keyguard.KeyguardUpdateMonitor
@@ -258,6 +259,8 @@ interface KeyguardRepository {
val notificationStackAbsoluteBottom: StateFlow<Float>
+ val wallpaperFocalAreaBounds: StateFlow<RectF>
+
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
*
@@ -329,6 +332,8 @@ interface KeyguardRepository {
* this value
*/
fun setNotificationStackAbsoluteBottom(bottom: Float)
+
+ fun setWallpaperFocalAreaBounds(bounds: RectF)
}
/** Encapsulates application state for the keyguard. */
@@ -380,7 +385,6 @@ constructor(
override val onCameraLaunchDetected = MutableStateFlow(CameraLaunchSourceModel())
override val panelAlpha: MutableStateFlow<Float> = MutableStateFlow(1f)
-
override val topClippingBounds = MutableStateFlow<Int?>(null)
override val isKeyguardShowing: MutableStateFlow<Boolean> =
@@ -622,6 +626,10 @@ constructor(
private val _notificationStackAbsoluteBottom = MutableStateFlow(0F)
override val notificationStackAbsoluteBottom = _notificationStackAbsoluteBottom.asStateFlow()
+ private val _wallpaperFocalAreaBounds = MutableStateFlow(RectF(0F, 0F, 0F, 0F))
+ override val wallpaperFocalAreaBounds: StateFlow<RectF> =
+ _wallpaperFocalAreaBounds.asStateFlow()
+
init {
val callback =
object : KeyguardStateController.Callback {
@@ -700,6 +708,10 @@ constructor(
_notificationStackAbsoluteBottom.value = bottom
}
+ override fun setWallpaperFocalAreaBounds(bounds: RectF) {
+ _wallpaperFocalAreaBounds.value = bounds
+ }
+
private fun dozeMachineStateToModel(state: DozeMachine.State): DozeStateModel {
return when (state) {
DozeMachine.State.UNINITIALIZED -> DozeStateModel.UNINITIALIZED
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
index cb602f1287f7..d6a110a8fd55 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
@@ -22,10 +22,7 @@ import android.content.Context
import android.os.Binder
import android.os.IBinder
import android.os.RemoteException
-import android.os.UserManager
import android.provider.DeviceConfig
-import android.util.Log
-import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.CoreStartable
@@ -42,7 +39,6 @@ import com.android.systemui.navigation.domain.interactor.NavigationInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessModel
-import com.android.systemui.process.ProcessWrapper
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
@@ -53,10 +49,9 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext
-private val TAG = StatusBarDisableFlagsInteractor::class.simpleName
-
/**
* Logic around StatusBarService#disableForUser, which is used to disable the home and recents
* button in certain device states.
@@ -72,7 +67,6 @@ constructor(
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
private val statusBarService: IStatusBarService,
- private val processWrapper: ProcessWrapper,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
selectedUserInteractor: SelectedUserInteractor,
deviceConfigInteractor: DeviceConfigInteractor,
@@ -147,24 +141,6 @@ constructor(
return
}
- // TODO(b/341604160): Remove this blocking logic once StatusBarManagerService supports
- // visible background users properly.
- if (
- UserManager.isVisibleBackgroundUsersEnabled() &&
- !processWrapper.isSystemUser() &&
- !processWrapper.isForegroundUserOrProfile()
- ) {
- // Currently, only one SysUI process can register with IStatusBarService to listen
- // for the CommandQueue events.
- // In the Multi Display configuration with concurrent multi users (primarily used
- // in Automotive), a visible background user (Automotive Multi Display passengers)
- // could also access this code path. Given this limitation and we only allow the
- // current user's SysUI process to register with IStatusBarService, we need to prevent
- // calls into IStatusBarService from visible background users.
- Log.d(TAG, "Status bar manager is disabled for visible background users")
- return
- }
-
scope.launch {
disableFlagsForUserId.collect { (selectedUserId, flags) ->
if (context.getSystemService(Context.STATUS_BAR_SERVICE) == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt
new file mode 100644
index 000000000000..934afe248a36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractor.kt
@@ -0,0 +1,176 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.RectF
+import android.util.TypedValue
+import com.android.app.animation.MathUtils.max
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.res.R
+import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
+import com.android.systemui.wallpapers.data.repository.WallpaperRepository
+import javax.inject.Inject
+import kotlin.math.min
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.stateIn
+
+@SysUISingleton
+class WallpaperFocalAreaInteractor
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ context: Context,
+ private val keyguardRepository: KeyguardRepository,
+ shadeRepository: ShadeRepository,
+ activeNotificationsInteractor: ActiveNotificationsInteractor,
+ keyguardClockRepository: KeyguardClockRepository,
+ wallpaperRepository: WallpaperRepository,
+) {
+ // When there's notifications in splitshade, magic portrait shape effects should be left
+ // aligned in foldable
+ private val notificationInShadeWideLayout: Flow<Boolean> =
+ combine(
+ shadeRepository.isShadeLayoutWide,
+ activeNotificationsInteractor.areAnyNotificationsPresent,
+ ) { isShadeLayoutWide, areAnyNotificationsPresent: Boolean ->
+ when {
+ !isShadeLayoutWide -> false
+ !areAnyNotificationsPresent -> false
+ else -> true
+ }
+ }
+
+ val shouldSendFocalArea = wallpaperRepository.shouldSendFocalArea
+ val wallpaperFocalAreaBounds: StateFlow<RectF?> =
+ combine(
+ shadeRepository.isShadeLayoutWide,
+ notificationInShadeWideLayout,
+ keyguardRepository.notificationStackAbsoluteBottom,
+ keyguardRepository.shortcutAbsoluteTop,
+ keyguardClockRepository.notificationDefaultTop,
+ ) {
+ isShadeLayoutWide,
+ notificationInShadeWideLayout,
+ notificationStackAbsoluteBottom,
+ shortcutAbsoluteTop,
+ notificationDefaultTop ->
+ // Wallpaper will be zoomed in with config_wallpaperMaxScale in lockscreen
+ // so we need to give a bounds taking this scale in consideration
+ val wallpaperZoomedInScale = getSystemWallpaperMaximumScale(context)
+ val screenBounds =
+ RectF(
+ 0F,
+ 0F,
+ context.resources.displayMetrics.widthPixels.toFloat(),
+ context.resources.displayMetrics.heightPixels.toFloat(),
+ )
+ val scaledBounds =
+ RectF(
+ screenBounds.centerX() - screenBounds.width() / 2F / wallpaperZoomedInScale,
+ screenBounds.centerY() -
+ screenBounds.height() / 2F / wallpaperZoomedInScale,
+ screenBounds.centerX() + screenBounds.width() / 2F / wallpaperZoomedInScale,
+ screenBounds.centerY() + screenBounds.height() / 2F / wallpaperZoomedInScale,
+ )
+ val maxFocalAreaWidth =
+ TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ FOCAL_AREA_MAX_WIDTH_DP.toFloat(),
+ context.resources.displayMetrics,
+ )
+ val (left, right) =
+ // tablet landscape
+ if (context.resources.getBoolean(R.bool.center_align_magic_portrait_shape)) {
+ Pair(
+ scaledBounds.centerX() - maxFocalAreaWidth / 2F,
+ scaledBounds.centerX() + maxFocalAreaWidth / 2F,
+ )
+ // unfold foldable landscape
+ } else if (isShadeLayoutWide) {
+ if (notificationInShadeWideLayout) {
+ Pair(scaledBounds.left, scaledBounds.centerX())
+ } else {
+ Pair(scaledBounds.centerX(), scaledBounds.right)
+ }
+ // handheld / portrait
+ } else {
+ val focalAreaWidth = min(scaledBounds.width(), maxFocalAreaWidth)
+ Pair(
+ scaledBounds.centerX() - focalAreaWidth / 2F,
+ scaledBounds.centerX() + focalAreaWidth / 2F,
+ )
+ }
+ val scaledBottomMargin =
+ (context.resources.displayMetrics.heightPixels - shortcutAbsoluteTop) /
+ wallpaperZoomedInScale
+ val top =
+ // tablet landscape
+ if (context.resources.getBoolean(R.bool.center_align_magic_portrait_shape)) {
+ // no strict constraints for top, use bottom margin to make it symmetric
+ // vertically
+ scaledBounds.top + scaledBottomMargin
+ }
+ // unfold foldable landscape
+ else if (isShadeLayoutWide) {
+ // For all landscape, we should use bottom of smartspace to constrain
+ scaledBounds.top + notificationDefaultTop / wallpaperZoomedInScale
+ // handheld / portrait
+ } else {
+ scaledBounds.top +
+ max(notificationDefaultTop, notificationStackAbsoluteBottom) /
+ wallpaperZoomedInScale
+ }
+ val bottom = scaledBounds.bottom - scaledBottomMargin
+ RectF(left, top, right, bottom)
+ }
+ .stateIn(
+ applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = null,
+ )
+
+ fun setWallpaperFocalAreaBounds(bounds: RectF) {
+ keyguardRepository.setWallpaperFocalAreaBounds(bounds)
+ }
+
+ companion object {
+ fun getSystemWallpaperMaximumScale(context: Context): Float {
+ return context.resources.getFloat(
+ Resources.getSystem()
+ .getIdentifier(
+ /* name= */ "config_wallpaperMaxScale",
+ /* defType= */ "dimen",
+ /* defPackage= */ "android",
+ )
+ )
+ }
+
+ // A max width for magic portrait shape effects bounds, to avoid it going too large
+ // in large screen portrait mode
+ const val FOCAL_AREA_MAX_WIDTH_DP = 500
+ }
+}
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 6d270b219c81..d8bd4452f2a6 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
@@ -54,6 +54,7 @@ import com.android.systemui.customization.R as customR
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.keyguard.KeyguardViewMediator
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
+import com.android.systemui.keyguard.domain.interactor.WallpaperFocalAreaInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
@@ -87,6 +88,7 @@ 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
@@ -105,6 +107,7 @@ object KeyguardRootViewBinder {
screenOffAnimationController: ScreenOffAnimationController,
shadeInteractor: ShadeInteractor,
clockInteractor: KeyguardClockInteractor,
+ wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor,
clockViewModel: KeyguardClockViewModel,
interactionJankMonitor: InteractionJankMonitor?,
deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor?,
@@ -309,12 +312,15 @@ object KeyguardRootViewBinder {
.setTag(clockId)
jankMonitor.begin(builder)
}
+
TransitionState.CANCELED ->
jankMonitor.cancel(CUJ_SCREEN_OFF_SHOW_AOD)
+
TransitionState.FINISHED -> {
keyguardViewMediator?.maybeHandlePendingLock()
jankMonitor.end(CUJ_SCREEN_OFF_SHOW_AOD)
}
+
TransitionState.RUNNING -> Unit
}
}
@@ -378,6 +384,21 @@ object KeyguardRootViewBinder {
}
disposables +=
+ view.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ if (viewModel.shouldSendFocalArea.value) {
+ launch {
+ wallpaperFocalAreaInteractor.wallpaperFocalAreaBounds
+ .filterNotNull()
+ .collect {
+ wallpaperFocalAreaInteractor.setWallpaperFocalAreaBounds(it)
+ }
+ }
+ }
+ }
+ }
+
+ disposables +=
view.onLayoutChanged(
OnLayoutChange(
viewModel,
@@ -523,6 +544,7 @@ object KeyguardRootViewBinder {
View.INVISIBLE
}
}
+
else -> {
if (isVisible.value) {
CrossFadeHelper.fadeIn(this, animatorListener)
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 a2107871a585..7605bdd3d7b5 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
@@ -55,6 +55,7 @@ import com.android.systemui.customization.R as customR
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.domain.interactor.WallpaperFocalAreaInteractor
import com.android.systemui.keyguard.shared.model.ClockSizeSetting
import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder
@@ -117,6 +118,7 @@ constructor(
private val secureSettings: SecureSettings,
private val defaultShortcutsSection: DefaultShortcutsSection,
private val keyguardQuickAffordanceViewBinder: KeyguardQuickAffordanceViewBinder,
+ private val wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor,
) {
val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
private val width: Int = bundle.getInt(KEY_VIEW_WIDTH)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt
index 3eb8522e0338..542fb9b46bef 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt
@@ -23,10 +23,4 @@ data class BlurConfig(val minBlurRadiusPx: Float, val maxBlurRadiusPx: Float) {
// No-op config that will be used by dagger of other SysUI variants which don't blur the
// background surface.
@Inject constructor() : this(0.0f, 0.0f)
-
- companion object {
- // Blur the shade much lesser than the background surface so that the surface is
- // distinguishable from the background.
- @JvmStatic fun Float.maxBlurRadiusToNotificationPanelBlurRadius(): Float = this / 3.0f
- }
}
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 733d7d71061e..b531c7fa49ec 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
@@ -24,7 +24,6 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCE
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.BlurConfig
-import com.android.systemui.keyguard.ui.transitions.BlurConfig.Companion.maxBlurRadiusToNotificationPanelBlurRadius
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -89,9 +88,7 @@ constructor(
shadeDependentFlows.transitionFlow(
flowWhenShadeIsNotExpanded = emptyFlow(),
flowWhenShadeIsExpanded =
- transitionAnimation.immediatelyTransitionTo(
- blurConfig.maxBlurRadiusPx.maxBlurRadiusToNotificationPanelBlurRadius()
- ),
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
)
} else {
emptyFlow<Float>()
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 e51e05b8ab61..aa4293a201ac 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
@@ -28,6 +28,7 @@ import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.PulseExpansionInteractor
+import com.android.systemui.keyguard.domain.interactor.WallpaperFocalAreaInteractor
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
@@ -133,6 +134,7 @@ constructor(
private val screenOffAnimationController: ScreenOffAnimationController,
private val aodBurnInViewModel: AodBurnInViewModel,
private val shadeInteractor: ShadeInteractor,
+ wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor,
) {
val burnInLayerVisibility: Flow<Int> =
keyguardTransitionInteractor.startedKeyguardTransitionStep
@@ -362,6 +364,8 @@ constructor(
initialValue = AnimatedValue.NotAnimating(false),
)
+ val shouldSendFocalArea = wallpaperFocalAreaInteractor.shouldSendFocalArea
+
fun onNotificationContainerBoundsChanged(top: Float, bottom: Float, animate: Boolean = false) {
keyguardInteractor.setNotificationContainerBounds(
NotificationContainerBounds(top = top, bottom = bottom, isAnimated = animate)
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 44c4c8723dcb..89dcbf6aa52b 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
@@ -24,7 +24,6 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.BlurConfig
-import com.android.systemui.keyguard.ui.transitions.BlurConfig.Companion.maxBlurRadiusToNotificationPanelBlurRadius
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -88,9 +87,7 @@ constructor(
shadeDependentFlows.transitionFlow(
flowWhenShadeIsNotExpanded = emptyFlow(),
flowWhenShadeIsExpanded =
- transitionAnimation.immediatelyTransitionTo(
- blurConfig.maxBlurRadiusPx.maxBlurRadiusToNotificationPanelBlurRadius()
- ),
+ transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
)
} else {
emptyFlow()
diff --git a/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java b/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
index ad306694346e..e8ded03e3b38 100644
--- a/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
@@ -116,8 +116,8 @@ public class SessionTracker implements CoreStartable {
mSessionToInstanceId.put(type, instanceId);
if (UserManager.isVisibleBackgroundUsersEnabled() && !mProcessWrapper.isSystemUser()
- && !mProcessWrapper.isForegroundUserOrProfile()) {
- // TODO(b/341604160): Support visible background users properly.
+ && !mProcessWrapper.isForegroundUser()) {
+ // TODO: b/341604160 - Support visible background users properly.
if (DEBUG) {
Log.d(TAG, "Status bar manager is disabled for visible background users");
}
@@ -155,8 +155,8 @@ public class SessionTracker implements CoreStartable {
mUiEventLogger.log(endSessionUiEvent, instanceId);
}
if (UserManager.isVisibleBackgroundUsersEnabled() && !mProcessWrapper.isSystemUser()
- && !mProcessWrapper.isForegroundUserOrProfile()) {
- // TODO(b/341604160): Support visible background users properly.
+ && !mProcessWrapper.isForegroundUser()) {
+ // TODO: b/341604160 - Support visible background users properly.
if (DEBUG) {
Log.d(TAG, "Status bar manager is disabled for visible background users");
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 425e674ec804..fb69b793d975 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -21,6 +21,7 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferHelper.Companion.adjustMaxSize
import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
@SysUISingleton
@@ -31,7 +32,7 @@ constructor(
private val systemClock: SystemClock,
private val logcatEchoTracker: LogcatEchoTracker,
) {
- private val existingBuffers = mutableMapOf<String, TableLogBuffer>()
+ private val existingBuffers = ConcurrentHashMap<String, TableLogBuffer>()
/**
* Creates a new [TableLogBuffer]. This method should only be called from static contexts, where
@@ -42,17 +43,9 @@ constructor(
* @param maxSize the buffer max size. See [adjustMaxSize]
* @return a new [TableLogBuffer] registered with [DumpManager]
*/
- fun create(
- name: String,
- maxSize: Int,
- ): TableLogBuffer {
+ fun create(name: String, maxSize: Int): TableLogBuffer {
val tableBuffer =
- TableLogBuffer(
- adjustMaxSize(maxSize),
- name,
- systemClock,
- logcatEchoTracker,
- )
+ TableLogBuffer(adjustMaxSize(maxSize), name, systemClock, logcatEchoTracker)
dumpManager.registerTableLogBuffer(name, tableBuffer)
return tableBuffer
}
@@ -66,13 +59,12 @@ constructor(
*
* @return a [TableLogBuffer] suitable for reuse
*/
- fun getOrCreate(
- name: String,
- maxSize: Int,
- ): TableLogBuffer =
- existingBuffers.getOrElse(name) {
- val buffer = create(name, maxSize)
- existingBuffers[name] = buffer
- buffer
+ fun getOrCreate(name: String, maxSize: Int): TableLogBuffer =
+ synchronized(existingBuffers) {
+ existingBuffers.getOrElse(name) {
+ val buffer = create(name, maxSize)
+ existingBuffers[name] = buffer
+ buffer
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 173a964cc5d3..40197b2daf49 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -536,8 +536,10 @@ public final class NavBarHelper implements
}
/**
- * @return Whether the IME is shown on top of the screen given the {@code vis} flag of
- * {@link InputMethodService} and the keyguard states.
+ * Checks whether the IME is shown on top of the screen, based on the given IME window
+ * visibility flags, and the current keyguard state.
+ *
+ * @param vis the IME window visibility.
*/
public boolean isImeShown(@ImeWindowVisibility int vis) {
View shadeWindowView = mNotificationShadeWindowController.getWindowRootView();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index 05d8bff2ceb6..ee24b3120966 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -18,7 +18,7 @@ package com.android.systemui.navigationbar;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
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;
@@ -31,12 +31,13 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING;
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.WindowVisibleState;
import android.content.Context;
import android.graphics.Rect;
@@ -111,6 +112,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private TaskStackChangeListeners mTaskStackChangeListeners;
private Optional<Pip> mPipOptional;
private int mDefaultDisplayId;
+ @NavigationHint
private int mNavigationIconHints;
private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater =
new NavBarHelper.NavbarTaskbarStateUpdater() {
@@ -362,8 +364,8 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
.setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable)
.setFlag(SYSUI_STATE_IME_SHOWING,
(mNavigationIconHints & NAVIGATION_HINT_IME_SHOWN) != 0)
- .setFlag(SYSUI_STATE_IME_SWITCHER_SHOWING,
- (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_SHOWN) != 0)
+ .setFlag(SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING,
+ (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0)
.setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
(mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
.setFlag(SYSUI_STATE_HOME_DISABLED,
@@ -489,12 +491,14 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
imeShown = (vis & InputMethodService.IME_VISIBLE_IMPERCEPTIBLE) != 0;
}
showImeSwitcher = imeShown && showImeSwitcher;
- int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition,
+ int hints = Utilities.calculateNavigationIconHints(mNavigationIconHints, backDisposition,
imeShown, showImeSwitcher);
- if (hints != mNavigationIconHints) {
- mNavigationIconHints = hints;
- updateSysuiFlags();
+ if (hints == mNavigationIconHints) {
+ return;
}
+
+ mNavigationIconHints = hints;
+ updateSysuiFlags();
}
@Override
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 c78750718cf0..6842dbc2b12d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
@@ -18,11 +18,12 @@ package com.android.systemui.navigationbar.views;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
-import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
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.windowStateToString;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.view.InsetsSource.FLAG_SUPPRESS_SCRIM;
@@ -43,7 +44,7 @@ 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_IME_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING;
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;
@@ -56,6 +57,7 @@ import android.annotation.NonNull;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.StatusBarManager;
+import android.app.StatusBarManager.NavigationHint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
@@ -233,6 +235,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
+ @NavigationHint
private int mNavigationIconHints = 0;
private @TransitionMode int mTransitionMode;
private boolean mLongPressHomeEnabled;
@@ -817,7 +820,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
if (mSavedState != null) {
getBarTransitions().getLightTransitionsController().restoreState(mSavedState);
}
- setNavigationIconHints(mNavigationIconHints);
setWindowVisible(isNavBarWindowVisible());
mView.setBehavior(mBehavior);
setNavBarMode(mNavBarMode);
@@ -1111,6 +1113,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled);
pw.println(" mNavigationBarWindowState="
+ windowStateToString(mNavigationBarWindowState));
+ pw.println(" mNavigationIconHints=" + navigationHintsToString(mNavigationIconHints));
pw.println(" mTransitionMode="
+ BarTransitions.modeToString(mTransitionMode));
pw.println(" mTransientShown=" + mTransientShown);
@@ -1137,9 +1140,11 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
}
boolean imeShown = mNavBarHelper.isImeShown(vis);
showImeSwitcher = imeShown && showImeSwitcher;
- int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition,
+ int hints = Utilities.calculateNavigationIconHints(mNavigationIconHints, backDisposition,
imeShown, showImeSwitcher);
- if (hints == mNavigationIconHints) return;
+ if (hints == mNavigationIconHints) {
+ return;
+ }
setNavigationIconHints(hints);
checkBarModes();
@@ -1682,8 +1687,8 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
.setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isNavBarWindowVisible())
.setFlag(SYSUI_STATE_IME_SHOWING,
(mNavigationIconHints & NAVIGATION_HINT_IME_SHOWN) != 0)
- .setFlag(SYSUI_STATE_IME_SWITCHER_SHOWING,
- (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_SHOWN) != 0)
+ .setFlag(SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING,
+ (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0)
.setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
allowSystemGestureIgnoringBarVisibility())
.commitUpdate(mDisplayId);
@@ -1926,12 +1931,20 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
};
@VisibleForTesting
+ @NavigationHint
int getNavigationIconHints() {
return mNavigationIconHints;
}
- private void setNavigationIconHints(int hints) {
- if (hints == mNavigationIconHints) return;
+ /**
+ * Updates the navigation icons based on {@code hints}.
+ *
+ * @param hints bit flags defined in {@link StatusBarManager}.
+ */
+ private void setNavigationIconHints(@NavigationHint int hints) {
+ if (hints == mNavigationIconHints) {
+ 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;
@@ -1945,9 +1958,8 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mView.setNavigationIconHints(hints);
}
if (DEBUG) {
- android.widget.Toast.makeText(mContext,
- "Navigation icon hints = " + hints,
- 500).show();
+ android.widget.Toast.makeText(mContext, "Navigation icon hints = " + hints, 500)
+ .show();
}
mNavigationIconHints = hints;
}
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 d5ae72165c4a..ed8e538cc895 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
@@ -16,6 +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_SHOWN;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN;
import static android.inputmethodservice.InputMethodService.canImeRenderGesturalNavButtons;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -31,7 +34,7 @@ import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.DrawableRes;
-import android.app.StatusBarManager;
+import android.app.StatusBarManager.NavigationHint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
@@ -113,6 +116,7 @@ public class NavigationBarView extends FrameLayout {
boolean mLongClickableAccessibilityButton;
int mDisabledFlags = 0;
+ @NavigationHint
int mNavigationIconHints = 0;
private int mNavBarMode;
private boolean mImeDrawsImeNavBar;
@@ -499,8 +503,7 @@ public class NavigationBarView extends FrameLayout {
}
private void orientBackButton(KeyButtonDrawable drawable) {
- final boolean useAltBack =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+ final boolean useAltBack = (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0;
final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
if (drawable.getRotation() == degrees) {
@@ -555,8 +558,10 @@ public class NavigationBarView extends FrameLayout {
super.setLayoutDirection(layoutDirection);
}
- void setNavigationIconHints(int hints) {
- if (hints == mNavigationIconHints) return;
+ void setNavigationIconHints(@NavigationHint int hints) {
+ if (hints == mNavigationIconHints) {
+ return;
+ }
mNavigationIconHints = hints;
updateNavButtonIcons();
}
@@ -594,8 +599,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 & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+ final boolean useAltBack = (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0;
KeyButtonDrawable backIcon = mBackIcon;
orientBackButton(backIcon);
KeyButtonDrawable homeIcon = mHomeDefaultIcon;
@@ -607,11 +611,12 @@ public class NavigationBarView extends FrameLayout {
updateRecentsIcon();
- // Update IME button visibility, a11y and rotate button always overrides the appearance
- boolean disableImeSwitcher =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN) == 0
- || isImeRenderingNavButtons();
- mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher, !disableImeSwitcher);
+ // Update IME switcher button visibility, a11y and rotate button always overrides
+ // the appearance
+ boolean isImeSwitcherButtonVisible =
+ (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_BUTTON_SHOWN) != 0
+ && !isImeRenderingNavButtons();
+ mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher, isImeSwitcherButtonVisible);
mBarTransitions.reapplyDarkIntensity();
@@ -665,7 +670,7 @@ public class NavigationBarView extends FrameLayout {
boolean isImeRenderingNavButtons() {
return mImeDrawsImeNavBar
&& mImeCanRenderGesturalNavButtons
- && (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0;
+ && (mNavigationIconHints & NAVIGATION_HINT_IME_SHOWN) != 0;
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
index f3a3a3a2ac4c..294d0c75167a 100644
--- a/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
@@ -27,12 +27,8 @@ import javax.inject.Inject;
* providing a mockable target around these details.
*/
public class ProcessWrapper {
- private final ActivityManager mActivityManager;
-
@Inject
- public ProcessWrapper(ActivityManager activityManager) {
- mActivityManager = activityManager;
- }
+ public ProcessWrapper() {}
/**
* Returns {@code true} if System User is running the current process.
@@ -42,10 +38,10 @@ public class ProcessWrapper {
}
/**
- * Returns {@code true} if the foreground user or profile is running the current process.
+ * Returns {@code true} if the foreground user is running the current process.
*/
- public boolean isForegroundUserOrProfile() {
- return mActivityManager.isProfileForeground(myUserHandle());
+ public boolean isForegroundUser() {
+ return ActivityManager.getCurrentUser() == myUserHandle().getIdentifier();
}
/**
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 d2ee126ace91..2cccaddc02a8 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
@@ -498,11 +498,9 @@ fun gridHeight(rows: Int, tileHeight: Dp, tilePadding: Dp, gridPadding: Dp): Dp
return ((tileHeight + tilePadding) * rows) + gridPadding * 2
}
-private fun GridCell.key(index: Int, dragAndDropState: DragAndDropState): Any {
+private fun GridCell.key(index: Int): Any {
return when (this) {
- is TileGridCell -> {
- if (dragAndDropState.isMoving(tile.tileSpec)) index else key
- }
+ is TileGridCell -> key
is SpacerGridCell -> index
}
}
@@ -510,10 +508,13 @@ private fun GridCell.key(index: Int, dragAndDropState: DragAndDropState): Any {
/**
* Adds a list of [GridCell] to the lazy grid
*
- * @param cells the pairs of [GridCell] to [AnimatableTileViewModel]
+ * @param cells the pairs of [GridCell] to [BounceableTileViewModel]
+ * @param columns the number of columns of this tile grid
* @param dragAndDropState the [DragAndDropState] for this grid
* @param selectionState the [MutableSelectionState] for this grid
- * @param onToggleSize the callback when a tile's size is toggled
+ * @param coroutineScope the [CoroutineScope] to be used for the tiles
+ * @param largeTilesSpan the width used for large tiles
+ * @param onResize the callback when a tile has a new [ResizeOperation]
*/
fun LazyGridScope.EditTiles(
cells: List<Pair<GridCell, BounceableTileViewModel>>,
@@ -526,7 +527,7 @@ fun LazyGridScope.EditTiles(
) {
items(
count = cells.size,
- key = { cells[it].first.key(it, dragAndDropState) },
+ key = { cells[it].first.key(it) },
span = { cells[it].first.span },
contentType = { TileType },
) { index ->
@@ -536,13 +537,12 @@ fun LazyGridScope.EditTiles(
// If the tile is being moved, replace it with a visible spacer
SpacerGridCell(
Modifier.background(
- color =
- MaterialTheme.colorScheme.secondary.copy(
- alpha = EditModeTileDefaults.PLACEHOLDER_ALPHA
- ),
- shape = RoundedCornerShape(InactiveCornerRadius),
- )
- .animateItem()
+ color =
+ MaterialTheme.colorScheme.secondary.copy(
+ alpha = EditModeTileDefaults.PLACEHOLDER_ALPHA
+ ),
+ shape = RoundedCornerShape(InactiveCornerRadius),
+ )
)
} else {
TileGridCell(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
index 0051bf5de7f2..ad5dd27f07c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
@@ -35,12 +35,14 @@ import com.android.systemui.modes.shared.ModesUiIcons
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.plugins.qs.TileDetailsViewModel
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.QsEventLogger
import com.android.systemui.qs.asQSTileIcon
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.qs.tiles.dialog.ModesDetailsViewModel
import com.android.systemui.qs.tiles.impl.modes.domain.interactor.ModesTileDataInteractor
import com.android.systemui.qs.tiles.impl.modes.domain.interactor.ModesTileUserActionInteractor
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
@@ -48,6 +50,7 @@ import com.android.systemui.qs.tiles.impl.modes.ui.ModesTileMapper
import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
+import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel
import javax.inject.Inject
import kotlinx.coroutines.runBlocking
@@ -67,6 +70,7 @@ constructor(
private val dataInteractor: ModesTileDataInteractor,
private val tileMapper: ModesTileMapper,
private val userActionInteractor: ModesTileUserActionInteractor,
+ private val modesDialogViewModel: ModesDialogViewModel,
) :
QSTileImpl<QSTile.State>(
host,
@@ -114,6 +118,13 @@ constructor(
userActionInteractor.handleToggleClick(model)
}
+ override fun getDetailsViewModel(): TileDetailsViewModel {
+ return ModesDetailsViewModel(
+ onSettingsClick = { userActionInteractor.handleLongClick(null) },
+ viewModel = modesDialogViewModel,
+ )
+ }
+
override fun getLongClickIntent(): Intent = userActionInteractor.longClickIntent
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.kt
new file mode 100644
index 000000000000..511597d05d37
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsViewModel.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.qs.tiles.dialog
+
+import androidx.compose.runtime.Composable
+import com.android.systemui.plugins.qs.TileDetailsViewModel
+import com.android.systemui.statusbar.policy.ui.dialog.composable.ModeTileGrid
+import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel
+
+/** The view model used for the modes details view in the Quick Settings */
+class ModesDetailsViewModel(
+ private val onSettingsClick: () -> Unit,
+ private val viewModel: ModesDialogViewModel,
+) : TileDetailsViewModel() {
+ @Composable
+ override fun GetContentView() {
+ // TODO(b/378513940): Finish implementing this function.
+ ModeTileGrid(viewModel = viewModel)
+ }
+
+ override fun clickOnSettingsButton() {
+ onSettingsClick()
+ }
+
+ override fun getTitle(): String {
+ // TODO(b/388321032): Replace this string with a string in a translatable xml file.
+ return "Modes"
+ }
+
+ override fun getSubTitle(): String {
+ // TODO(b/388321032): Replace this string with a string in a translatable xml file.
+ return "Silences interruptions from people and apps in different circumstances"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractor.kt
index 5ce7f0d039c8..b5da044b886a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractor.kt
@@ -54,7 +54,7 @@ constructor(
handleToggleClick(input.data)
}
is QSTileUserAction.LongClick -> {
- qsTileIntentUserInputHandler.handle(action.expandable, longClickIntent)
+ handleLongClick(action.expandable)
}
}
}
@@ -95,6 +95,10 @@ constructor(
}
}
+ fun handleLongClick(expandable: Expandable?) {
+ qsTileIntentUserInputHandler.handle(expandable, longClickIntent)
+ }
+
companion object {
const val TAG = "ModesTileUserActionInteractor"
}
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 ecd002705c60..63c10c9b971a 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
@@ -945,10 +945,6 @@ constructor(
override fun onTransitionAnimationEnd() {
sceneInteractor.onTransitionAnimationEnd()
}
-
- override fun onTransitionAnimationCancelled() {
- sceneInteractor.onTransitionAnimationCancelled()
- }
}
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
index 49f3cfc4ceaf..917869a66ca4 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
@@ -27,6 +27,8 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
+import android.graphics.RenderEffect;
+import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.util.AttributeSet;
@@ -373,4 +375,18 @@ public class ScrimView extends View {
((ScrimDrawable) mDrawable).setRoundedCorners(radius);
}
}
+
+ /**
+ * Blur the view with the specific blur radius or clear any blurs if the radius is 0
+ */
+ public void setBlurRadius(float blurRadius) {
+ if (blurRadius > 0) {
+ setRenderEffect(RenderEffect.createBlurEffect(
+ blurRadius,
+ blurRadius,
+ Shader.TileMode.CLAMP));
+ } else {
+ setRenderEffect(null);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 19bf4c0bab81..a1b4def09ba9 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -109,7 +109,6 @@ import com.android.systemui.keyguard.shared.model.Edge;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.keyguard.ui.binder.KeyguardLongPressViewBinder;
-import com.android.systemui.keyguard.ui.transitions.BlurConfig;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardTouchHandlingViewModel;
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
@@ -915,8 +914,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
if (!com.android.systemui.Flags.bouncerUiRevamp()) return;
if (isBouncerShowing && isExpanded()) {
- float shadeBlurEffect = BlurConfig.maxBlurRadiusToNotificationPanelBlurRadius(
- mDepthController.getMaxBlurRadiusPx());
+ float shadeBlurEffect = mDepthController.getMaxBlurRadiusPx();
mView.setRenderEffect(RenderEffect.createBlurEffect(
shadeBlurEffect,
shadeBlurEffect,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index 48bbb0407ee3..48e374746bf5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -17,6 +17,7 @@
package com.android.systemui.shade;
import static android.os.Trace.TRACE_TAG_APP;
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
import static com.android.systemui.Flags.enableViewCaptureTracing;
import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;
@@ -49,10 +50,12 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowInsetsController;
+import android.view.accessibility.AccessibilityEvent;
import com.android.app.viewcapture.ViewCaptureFactory;
import com.android.internal.view.FloatingActionMode;
import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
+import com.android.systemui.Flags;
import com.android.systemui.scene.ui.view.WindowRootView;
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround;
import com.android.systemui.statusbar.phone.ConfigurationForwarder;
@@ -77,6 +80,8 @@ public class NotificationShadeWindowView extends WindowRootView {
private SafeCloseable mViewCaptureCloseable;
+ private boolean mAnimatingContentLaunch = false;
+
public NotificationShadeWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
@@ -188,6 +193,22 @@ public class NotificationShadeWindowView extends WindowRootView {
}
}
+ @Override
+ public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ if (Flags.shadeLaunchAccessibility() && mAnimatingContentLaunch
+ && event.getEventType() == TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
+ // Block accessibility focus events during launch animations to avoid stray TalkBack
+ // announcements.
+ return false;
+ }
+
+ return super.requestSendAccessibilityEvent(child, event);
+ }
+
+ public void setAnimatingContentLaunch(boolean animating) {
+ mAnimatingContentLaunch = animating;
+ }
+
public void setConfigurationForwarder(ConfigurationForwarder configurationForwarder) {
ShadeWindowGoesAround.isUnexpectedlyInLegacyMode();
mConfigurationForwarder = configurationForwarder;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index e5dcd2338b9d..ffec8f284c48 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -16,10 +16,12 @@
package com.android.systemui.shade;
+import static com.android.systemui.Flags.shadeLaunchAccessibility;
import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING;
import static com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.combineFlows;
import android.app.StatusBarManager;
import android.util.Log;
@@ -59,6 +61,7 @@ import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor;
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor;
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround;
import com.android.systemui.shared.animation.DisableSubpixelTextTransitionListener;
import com.android.systemui.statusbar.BlurUtils;
@@ -85,6 +88,7 @@ import com.android.systemui.window.ui.WindowRootViewBinder;
import com.android.systemui.window.ui.viewmodel.WindowRootViewModel;
import kotlinx.coroutines.ExperimentalCoroutinesApi;
+import kotlinx.coroutines.flow.Flow;
import java.io.PrintWriter;
import java.util.Optional;
@@ -174,6 +178,7 @@ public class NotificationShadeWindowViewController implements Dumpable {
NotificationShadeDepthController depthController,
NotificationShadeWindowView notificationShadeWindowView,
ShadeViewController shadeViewController,
+ ShadeAnimationInteractor shadeAnimationInteractor,
PanelExpansionInteractor panelExpansionInteractor,
ShadeExpansionStateManager shadeExpansionStateManager,
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
@@ -238,9 +243,17 @@ public class NotificationShadeWindowViewController implements Dumpable {
collectFlow(mView, keyguardTransitionInteractor.transition(
Edge.create(LOCKSCREEN, DREAMING)),
mLockscreenToDreamingTransition);
+ Flow<Boolean> isLaunchAnimationRunning =
+ shadeLaunchAccessibility()
+ ? combineFlows(
+ notificationLaunchAnimationInteractor.isLaunchAnimationRunning(),
+ shadeAnimationInteractor.isLaunchingActivity(),
+ (notificationLaunching, shadeLaunching) ->
+ notificationLaunching || shadeLaunching)
+ : notificationLaunchAnimationInteractor.isLaunchAnimationRunning();
collectFlow(
mView,
- notificationLaunchAnimationInteractor.isLaunchAnimationRunning(),
+ isLaunchAnimationRunning,
this::setExpandAnimationRunning);
if (QSComposeFragment.isEnabled()) {
collectFlow(mView,
@@ -726,9 +739,17 @@ public class NotificationShadeWindowViewController implements Dumpable {
if (ActivityTransitionAnimator.DEBUG_TRANSITION_ANIMATION) {
Log.d(TAG, "Setting mExpandAnimationRunning=" + running);
}
+
if (running) {
mLaunchAnimationTimeout = mClock.uptimeMillis() + 5000;
}
+
+ if (shadeLaunchAccessibility()) {
+ // The view needs to know when an animation is ongoing so it can intercept
+ // unnecessary accessibility events.
+ mView.setAnimatingContentLaunch(running);
+ }
+
mExpandAnimationRunning = running;
mNotificationShadeWindowController.setLaunchingActivity(mExpandAnimationRunning);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 7fc1510f1136..dcea8d85e10d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -273,12 +273,12 @@ public class CommandQueue extends IStatusBar.Stub implements
default void toggleQuickSettingsPanel() { }
/**
- * Called to notify IME window status changes.
+ * Sets the new IME window status.
*
- * @param displayId The id of the display to notify.
- * @param vis IME visibility.
- * @param backDisposition Disposition mode of back button.
- * @param showImeSwitcher {@code true} to show IME switch button.
+ * @param displayId The id of the display to which the IME is bound.
+ * @param vis The IME window visibility.
+ * @param backDisposition The IME back disposition mode.
+ * @param showImeSwitcher Whether the IME Switcher button should be shown.
*/
default void setImeWindowStatus(int displayId, @ImeWindowVisibility int vis,
@BackDispositionMode int backDisposition, boolean showImeSwitcher) { }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index ccea254defaa..4c6fa4839e5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -284,7 +284,8 @@ public class NotificationListener extends NotificationListenerWithPlugins implem
/* rankingAdjustment= */ 0,
/* isBubble= */ false,
/* proposedImportance= */ 0,
- /* sensitiveContent= */ false
+ /* sensitiveContent= */ false,
+ /* summarization = */ null
);
}
return ranking;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index 1965b9538df0..f7401440cfcb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -36,6 +36,8 @@ import com.android.systemui.util.kotlin.DisposableHandles
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
/** Binds the shared notification container to its view-model. */
@SysUISingleton
@@ -143,21 +145,25 @@ constructor(
if (!SceneContainerFlag.isEnabled) {
if (Flags.magicPortraitWallpapers()) {
launch {
- viewModel
- .getNotificationStackAbsoluteBottom(
- calculateMaxNotifications = calculateMaxNotifications,
- calculateHeight = { maxNotifications ->
- notificationStackSizeCalculator.computeHeight(
- maxNotifs = maxNotifications,
- shelfHeight = controller.getShelfHeight().toFloat(),
- stack = controller.view,
- )
- },
- controller.getShelfHeight().toFloat(),
+ combine(
+ viewModel.getNotificationStackAbsoluteBottom(
+ calculateMaxNotifications = calculateMaxNotifications,
+ calculateHeight = { maxNotifications ->
+ notificationStackSizeCalculator.computeHeight(
+ maxNotifs = maxNotifications,
+ shelfHeight =
+ controller.getShelfHeight().toFloat(),
+ stack = controller.view,
+ )
+ },
+ controller.getShelfHeight().toFloat(),
+ ),
+ viewModel.configurationBasedDimensions.map { it.marginTop },
+ ::Pair,
)
- .collect { bottom ->
+ .collect { (bottom: Float, marginTop: Int) ->
keyguardInteractor.setNotificationStackAbsoluteBottom(
- bottom
+ marginTop + bottom
)
}
}
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 0f6c3069609e..be48c3d928f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -66,6 +66,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.keyguard.shared.model.ScrimAlpha;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
+import com.android.systemui.keyguard.ui.transitions.BlurConfig;
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
import com.android.systemui.res.R;
@@ -258,6 +259,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private int mScrimsVisibility;
private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+ private final BlurConfig mBlurConfig;
private Consumer<Integer> mScrimVisibleListener;
private boolean mBlankScreen;
private boolean mScreenBlankingCallbackCalled;
@@ -339,9 +341,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
KeyguardTransitionInteractor keyguardTransitionInteractor,
KeyguardInteractor keyguardInteractor,
@Main CoroutineDispatcher mainDispatcher,
- LargeScreenShadeInterpolator largeScreenShadeInterpolator) {
+ LargeScreenShadeInterpolator largeScreenShadeInterpolator,
+ BlurConfig blurConfig) {
mScrimStateListener = lightBarController::setScrimState;
mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
+ mBlurConfig = blurConfig;
// All scrims default alpha need to match bouncer background alpha to make sure the
// transitions involving the bouncer are smooth and don't overshoot the bouncer alpha.
mDefaultScrimAlpha =
@@ -406,7 +410,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
final ScrimState[] states = ScrimState.values();
for (int i = 0; i < states.length; i++) {
- states[i].init(mScrimInFront, mScrimBehind, mDozeParameters, mDockManager);
+ states[i].init(mScrimInFront, mScrimBehind, mDozeParameters, mDockManager, mBlurConfig);
states[i].setScrimBehindAlphaKeyguard(mScrimBehindAlphaKeyguard);
states[i].setDefaultScrimAlpha(mDefaultScrimAlpha);
}
@@ -868,7 +872,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
* bounds instead.
*/
public void setClipsQsScrim(boolean clipScrim) {
- if (Flags.notificationShadeBlur()) {
+ if (Flags.notificationShadeBlur() || Flags.bouncerUiRevamp()) {
// Never clip scrims when blur is enabled, colors of UI elements are supposed to "add"
// up across the scrims.
mClipsQsScrim = false;
@@ -1210,6 +1214,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
dispatchBackScrimState(mScrimBehind.getViewAlpha());
}
+ if (Flags.bouncerUiRevamp()) {
+ // Blur the notification scrim as needed. The blur is needed only when we show the
+ // expanded shade behind the bouncer. Without it, the notification scrim outline is
+ // visible behind the bouncer.
+ mNotificationsScrim.setBlurRadius(mState.getNotifBlurRadius());
+ }
// We also want to hide FLAG_SHOW_WHEN_LOCKED activities under the scrim.
boolean hideFlagShowWhenLockedActivities =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 8170e6d91a0f..5f423cf35edd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -24,6 +24,7 @@ import android.graphics.Color;
import com.android.app.tracing.coroutines.TrackTracer;
import com.android.systemui.Flags;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.keyguard.ui.transitions.BlurConfig;
import com.android.systemui.res.R;
import com.android.systemui.scrim.ScrimView;
import com.android.systemui.shade.ui.ShadeColors;
@@ -149,7 +150,14 @@ public enum ScrimState {
@Override
public void prepare(ScrimState previousState) {
if (Flags.bouncerUiRevamp()) {
- mBehindAlpha = 0f;
+ if (previousState == SHADE_LOCKED) {
+ mBehindAlpha = previousState.getBehindAlpha();
+ mNotifAlpha = previousState.getNotifAlpha();
+ mNotifBlurRadius = mBlurConfig.getMaxBlurRadiusPx();
+ } else {
+ mNotifAlpha = 0f;
+ mBehindAlpha = 0f;
+ }
mFrontAlpha = TRANSPARENT_BOUNCER_SCRIM_ALPHA;
mFrontTint = mSurfaceColor;
return;
@@ -395,6 +403,7 @@ public enum ScrimState {
DozeParameters mDozeParameters;
DockManager mDockManager;
boolean mDisplayRequiresBlanking;
+ protected BlurConfig mBlurConfig;
boolean mLaunchingAffordanceWithPreview;
boolean mOccludeAnimationPlaying;
boolean mWakeLockScreenSensorActive;
@@ -403,8 +412,12 @@ public enum ScrimState {
boolean mClipQsScrim;
int mBackgroundColor;
+ // This is needed to blur the scrim behind the scrimmed bouncer to avoid showing
+ // the notification section border
+ protected float mNotifBlurRadius = 0.0f;
+
public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters,
- DockManager dockManager) {
+ DockManager dockManager, BlurConfig blurConfig) {
mBackgroundColor = scrimBehind.getContext().getColor(R.color.shade_scrim_background_dark);
mScrimInFront = scrimInFront;
mScrimBehind = scrimBehind;
@@ -412,6 +425,7 @@ public enum ScrimState {
mDozeParameters = dozeParameters;
mDockManager = dockManager;
mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
+ mBlurConfig = blurConfig;
}
/** Prepare state for transition. */
@@ -518,4 +532,8 @@ public enum ScrimState {
public void setClipQsScrim(boolean clipsQsScrim) {
mClipQsScrim = clipsQsScrim;
}
+
+ public float getNotifBlurRadius() {
+ return mNotifBlurRadius;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTransitionAnimatorController.kt
index 705a11df83fc..e12b21eb2c4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTransitionAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTransitionAnimatorController.kt
@@ -1,6 +1,7 @@
package com.android.systemui.statusbar.phone
import android.view.View
+import com.android.systemui.Flags
import com.android.systemui.animation.ActivityTransitionAnimator
import com.android.systemui.animation.TransitionAnimator
import com.android.systemui.animation.TransitionAnimator.Companion.getProgress
@@ -22,7 +23,7 @@ class StatusBarTransitionAnimatorController(
private val notificationShadeWindowController: NotificationShadeWindowController,
private val commandQueue: CommandQueue,
@DisplayId private val displayId: Int,
- private val isLaunchForActivity: Boolean = true
+ private val isLaunchForActivity: Boolean = true,
) : ActivityTransitionAnimator.Controller by delegate {
private var hideIconsDuringLaunchAnimation: Boolean = true
@@ -41,8 +42,16 @@ class StatusBarTransitionAnimatorController(
}
override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
- delegate.onTransitionAnimationStart(isExpandingFullyAbove)
- shadeAnimationInteractor.setIsLaunchingActivity(true)
+ if (Flags.shadeLaunchAccessibility()) {
+ // We set this before calling the delegate to make sure that accessibility is disabled
+ // for the whole duration of the transition, so that we don't have stray TalkBack events
+ // once the animating view becomes invisible.
+ shadeAnimationInteractor.setIsLaunchingActivity(true)
+ delegate.onTransitionAnimationStart(isExpandingFullyAbove)
+ } else {
+ delegate.onTransitionAnimationStart(isExpandingFullyAbove)
+ shadeAnimationInteractor.setIsLaunchingActivity(true)
+ }
if (!isExpandingFullyAbove) {
shadeController.collapseWithDuration(
ActivityTransitionAnimator.TIMINGS.totalDuration.toInt()
@@ -59,7 +68,7 @@ class StatusBarTransitionAnimatorController(
override fun onTransitionAnimationProgress(
state: TransitionAnimator.State,
progress: Float,
- linearProgress: Float
+ linearProgress: Float,
) {
delegate.onTransitionAnimationProgress(state, progress, linearProgress)
val hideIcons =
@@ -67,7 +76,7 @@ class StatusBarTransitionAnimatorController(
ActivityTransitionAnimator.TIMINGS,
linearProgress,
ANIMATION_DELAY_ICON_FADE_IN,
- 100
+ 100,
) == 0.0f
if (hideIcons != hideIconsDuringLaunchAnimation) {
hideIconsDuringLaunchAnimation = hideIcons
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt
index 39b434ad65f1..83b7c1818341 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt
@@ -16,7 +16,6 @@
package com.android.systemui.volume.dialog
-import android.app.Dialog
import android.content.Context
import android.graphics.PixelFormat
import android.os.Bundle
@@ -24,6 +23,7 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
+import androidx.activity.ComponentDialog
import com.android.app.tracing.coroutines.coroutineScopeTraced
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.lifecycle.repeatWhenAttached
@@ -40,7 +40,7 @@ constructor(
@Application context: Context,
private val componentFactory: VolumeDialogComponent.Factory,
private val visibilityInteractor: VolumeDialogVisibilityInteractor,
-) : Dialog(context, R.style.Theme_SystemUI_Dialog_Volume) {
+) : ComponentDialog(context, R.style.Theme_SystemUI_Dialog_Volume) {
init {
with(window!!) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
index 940c79c78d76..577e47bb3b83 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
@@ -18,7 +18,6 @@ package com.android.systemui.volume.dialog.sliders.dagger
import com.android.systemui.volume.dialog.sliders.domain.model.VolumeDialogSliderType
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogOverscrollViewBinder
-import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderHapticsViewBinder
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderViewBinder
import dagger.BindsInstance
import dagger.Subcomponent
@@ -33,8 +32,6 @@ interface VolumeDialogSliderComponent {
fun sliderViewBinder(): VolumeDialogSliderViewBinder
- fun sliderHapticsViewBinder(): VolumeDialogSliderHapticsViewBinder
-
fun overscrollViewBinder(): VolumeDialogOverscrollViewBinder
@Subcomponent.Factory
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt
index 82885d65c513..07954f850286 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt
@@ -16,8 +16,8 @@
package com.android.systemui.volume.dialog.sliders.data.repository
-import android.view.MotionEvent
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
+import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -26,10 +26,11 @@ import kotlinx.coroutines.flow.filterNotNull
@VolumeDialogSliderScope
class VolumeDialogSliderTouchEventsRepository @Inject constructor() {
- private val mutableSliderTouchEvents: MutableStateFlow<MotionEvent?> = MutableStateFlow(null)
- val sliderTouchEvent: Flow<MotionEvent> = mutableSliderTouchEvents.filterNotNull()
+ private val mutableSliderTouchEvents: MutableStateFlow<SliderInputEvent.Touch?> =
+ MutableStateFlow(null)
+ val sliderTouchEvent: Flow<SliderInputEvent.Touch> = mutableSliderTouchEvents.filterNotNull()
- fun update(event: MotionEvent) {
- mutableSliderTouchEvents.tryEmit(MotionEvent.obtain(event))
+ fun update(touch: SliderInputEvent.Touch) {
+ mutableSliderTouchEvents.value = touch
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractor.kt
index c7b4184a9f2f..351832bd275a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInputEventsInteractor.kt
@@ -16,7 +16,6 @@
package com.android.systemui.volume.dialog.sliders.domain.interactor
-import android.view.MotionEvent
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogCallbacksInteractor
import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor
@@ -45,7 +44,7 @@ constructor(
val event: Flow<SliderInputEvent> =
merge(
- repository.sliderTouchEvent.map { SliderInputEvent.Touch(it) },
+ repository.sliderTouchEvent,
volumeDialogCallbacksInteractor.event
.filterIsInstance(VolumeDialogEventModel.VolumeChangedFromKey::class)
.map { SliderInputEvent.Button },
@@ -55,7 +54,7 @@ constructor(
event.onEach { visibilityInteractor.resetDismissTimeout() }.launchIn(coroutineScope)
}
- fun onTouchEvent(newEvent: MotionEvent) {
- repository.update(newEvent)
+ fun onTouchEvent(pointerEvent: SliderInputEvent.Touch) {
+ repository.update(pointerEvent)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/shared/model/SliderInputEvent.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/shared/model/SliderInputEvent.kt
index 37dbb4b3a81d..841730857d71 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/shared/model/SliderInputEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/shared/model/SliderInputEvent.kt
@@ -16,12 +16,20 @@
package com.android.systemui.volume.dialog.sliders.shared.model
-import android.view.MotionEvent
-
/** Models input event happened on the Volume Slider */
sealed interface SliderInputEvent {
- data class Touch(val event: MotionEvent) : SliderInputEvent
+ interface Touch : SliderInputEvent {
+
+ val x: Float
+ val y: Float
+
+ data class Start(override val x: Float, override val y: Float) : Touch
+
+ data class Move(override val x: Float, override val y: Float) : Touch
+
+ data class End(override val x: Float, override val y: Float) : Touch
+ }
data object Button : SliderInputEvent
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
index 8109b50aa34a..38feb69aad7b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
@@ -20,11 +20,9 @@ import android.view.View
import androidx.dynamicanimation.animation.FloatValueHolder
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
-import com.android.systemui.res.R
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel.OverscrollEventModel
-import com.google.android.material.slider.Slider
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
@@ -51,10 +49,6 @@ constructor(private val viewModel: VolumeDialogOverscrollViewModel) {
)
.addUpdateListener { _, value, _ -> viewsToAnimate.setTranslationY(value) }
- view.requireViewById<Slider>(R.id.volume_dialog_slider).addOnChangeListener { s, value, _ ->
- viewModel.setSlider(value = value, min = s.valueFrom, max = s.valueTo)
- }
-
viewModel.overscrollEvent
.onEach { event ->
when (event) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinder.kt
deleted file mode 100644
index 5a7fbc6341f2..000000000000
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinder.kt
+++ /dev/null
@@ -1,82 +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.volume.dialog.sliders.ui
-
-import android.view.View
-import com.android.systemui.haptics.slider.HapticSlider
-import com.android.systemui.haptics.slider.HapticSliderPlugin
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.util.time.SystemClock
-import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
-import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
-import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderInputEventsViewModel
-import com.google.android.material.slider.Slider
-import com.google.android.msdl.domain.MSDLPlayer
-import javax.inject.Inject
-import kotlin.math.roundToInt
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-
-@VolumeDialogSliderScope
-class VolumeDialogSliderHapticsViewBinder
-@Inject
-constructor(
- private val inputEventsViewModel: VolumeDialogSliderInputEventsViewModel,
- private val vibratorHelper: VibratorHelper,
- private val msdlPlayer: MSDLPlayer,
- private val systemClock: SystemClock,
-) {
-
- fun CoroutineScope.bind(view: View) {
- val sliderView = view.requireViewById<Slider>(R.id.volume_dialog_slider)
- val hapticSliderPlugin =
- HapticSliderPlugin(
- slider = HapticSlider.Slider(sliderView),
- vibratorHelper = vibratorHelper,
- msdlPlayer = msdlPlayer,
- systemClock = systemClock,
- )
- hapticSliderPlugin.startInScope(this)
-
- sliderView.addOnChangeListener { _, value, fromUser ->
- hapticSliderPlugin.onProgressChanged(value.roundToInt(), fromUser)
- }
- sliderView.addOnSliderTouchListener(
- object : Slider.OnSliderTouchListener {
-
- override fun onStartTrackingTouch(slider: Slider) {
- hapticSliderPlugin.onStartTrackingTouch()
- }
-
- override fun onStopTrackingTouch(slider: Slider) {
- hapticSliderPlugin.onStopTrackingTouch()
- }
- }
- )
-
- inputEventsViewModel.event
- .onEach {
- when (it) {
- is SliderInputEvent.Button -> hapticSliderPlugin.onKeyDown()
- is SliderInputEvent.Touch -> hapticSliderPlugin.onTouchEvent(it.event)
- }
- }
- .launchIn(this)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
index d40302408dd6..21a392776235 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
@@ -16,96 +16,211 @@
package com.android.systemui.volume.dialog.sliders.ui
-import android.annotation.SuppressLint
+import android.graphics.drawable.Drawable
import android.view.View
-import androidx.dynamicanimation.animation.FloatPropertyCompat
-import androidx.dynamicanimation.animation.SpringAnimation
-import androidx.dynamicanimation.animation.SpringForce
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.SliderDefaults
+import androidx.compose.material3.SliderState
+import androidx.compose.material3.VerticalSlider
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.compose.ui.graphics.painter.DrawablePainter
+import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel
+import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
-import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderInputEventsViewModel
-import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderStateModel
+import com.android.systemui.volume.dialog.sliders.ui.compose.VolumeDialogSliderTrack
+import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderViewModel
-import com.google.android.material.slider.Slider
-import com.google.android.material.slider.Slider.OnSliderTouchListener
+import com.android.systemui.volume.haptics.ui.VolumeHapticsConfigsProvider
import javax.inject.Inject
+import kotlin.math.round
import kotlin.math.roundToInt
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.currentCoroutineContext
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.isActive
@VolumeDialogSliderScope
class VolumeDialogSliderViewBinder
@Inject
constructor(
private val viewModel: VolumeDialogSliderViewModel,
- private val inputViewModel: VolumeDialogSliderInputEventsViewModel,
+ private val overscrollViewModel: VolumeDialogOverscrollViewModel,
+ private val hapticsViewModelFactory: SliderHapticsViewModel.Factory,
) {
+ fun bind(view: View) {
+ val sliderComposeView: ComposeView = view.requireViewById(R.id.volume_dialog_slider)
+ sliderComposeView.setContent {
+ VolumeDialogSlider(
+ viewModel = viewModel,
+ overscrollViewModel = overscrollViewModel,
+ hapticsViewModelFactory =
+ if (com.android.systemui.Flags.hapticsForComposeSliders()) {
+ hapticsViewModelFactory
+ } else {
+ null
+ },
+ )
+ }
+ }
+}
- private val sliderValueProperty =
- object : FloatPropertyCompat<Slider>("value") {
- override fun getValue(slider: Slider): Float = slider.value
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+@Composable
+private fun VolumeDialogSlider(
+ viewModel: VolumeDialogSliderViewModel,
+ overscrollViewModel: VolumeDialogOverscrollViewModel,
+ hapticsViewModelFactory: SliderHapticsViewModel.Factory?,
+ modifier: Modifier = Modifier,
+) {
+
+ val colors =
+ SliderDefaults.colors(
+ thumbColor = MaterialTheme.colorScheme.primary,
+ activeTickColor = MaterialTheme.colorScheme.surfaceContainerHighest,
+ inactiveTickColor = MaterialTheme.colorScheme.primary,
+ activeTrackColor = MaterialTheme.colorScheme.primary,
+ inactiveTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
+ )
+ val collectedSliderState by viewModel.state.collectAsStateWithLifecycle(null)
+ val sliderState = collectedSliderState ?: return
- override fun setValue(slider: Slider, value: Float) {
- slider.value = value
+ val interactionSource = remember { MutableInteractionSource() }
+ val hapticsViewModel: SliderHapticsViewModel? =
+ hapticsViewModelFactory?.let {
+ rememberViewModel(traceName = "SliderHapticsViewModel") {
+ it.create(
+ interactionSource,
+ sliderState.valueRange,
+ Orientation.Vertical,
+ VolumeHapticsConfigsProvider.sliderHapticFeedbackConfig(sliderState.valueRange),
+ VolumeHapticsConfigsProvider.seekableSliderTrackerConfig,
+ )
}
}
- private val springForce =
- SpringForce().apply {
- stiffness = SpringForce.STIFFNESS_MEDIUM
- dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY
- }
- @SuppressLint("ClickableViewAccessibility")
- fun CoroutineScope.bind(view: View) {
- var isInitialUpdate = true
- val sliderView: Slider = view.requireViewById(R.id.volume_dialog_slider)
- val animation = SpringAnimation(sliderView, sliderValueProperty)
- animation.spring = springForce
- sliderView.setOnTouchListener { _, event ->
- inputViewModel.onTouchEvent(event)
- false
- }
- sliderView.addOnChangeListener { _, value, fromUser ->
- viewModel.setStreamVolume(value.roundToInt(), fromUser)
+ val state =
+ remember(sliderState.valueRange) {
+ SliderState(
+ value = sliderState.value,
+ valueRange = sliderState.valueRange,
+ steps =
+ (sliderState.valueRange.endInclusive - sliderState.valueRange.start - 1)
+ .toInt(),
+ )
+ .apply {
+ onValueChangeFinished = {
+ viewModel.onStreamChangeFinished(value.roundToInt())
+ hapticsViewModel?.onValueChangeEnded()
+ }
+ setOnValueChangeListener {
+ value = it
+ hapticsViewModel?.addVelocityDataPoint(it)
+ overscrollViewModel.setSlider(
+ value = value,
+ min = valueRange.start,
+ max = valueRange.endInclusive,
+ )
+ viewModel.setStreamVolume(it, true)
+ }
+ }
}
- sliderView.addOnSliderTouchListener(
- object : OnSliderTouchListener {
- override fun onStartTrackingTouch(slider: Slider) {}
+ var lastDiscreteStep by remember { mutableFloatStateOf(round(sliderState.value)) }
+ LaunchedEffect(sliderState.value) {
+ state.value = sliderState.value
+ snapshotFlow { sliderState.value }
+ .map { round(it) }
+ .filter { it != lastDiscreteStep }
+ .distinctUntilChanged()
+ .collect { discreteStep ->
+ lastDiscreteStep = discreteStep
+ hapticsViewModel?.onValueChange(discreteStep)
+ }
+ }
- override fun onStopTrackingTouch(slider: Slider) {
- viewModel.onStreamChangeFinished(slider.value.roundToInt())
+ VerticalSlider(
+ state = state,
+ enabled = !sliderState.isDisabled,
+ reverseDirection = true,
+ colors = colors,
+ interactionSource = interactionSource,
+ modifier =
+ modifier.pointerInput(Unit) {
+ coroutineScope {
+ val currentContext = currentCoroutineContext()
+ awaitPointerEventScope {
+ while (currentContext.isActive) {
+ viewModel.onTouchEvent(awaitPointerEvent())
+ }
+ }
}
- }
- )
+ },
+ track = {
+ VolumeDialogSliderTrack(
+ state,
+ colors = colors,
+ isEnabled = !sliderState.isDisabled,
+ activeTrackEndIcon = { iconsState ->
+ VolumeIcon(sliderState.icon, iconsState.isActiveTrackEndIconVisible)
+ },
+ inactiveTrackEndIcon = { iconsState ->
+ VolumeIcon(sliderState.icon, !iconsState.isActiveTrackEndIconVisible)
+ },
+ )
+ },
+ )
+}
- viewModel.isDisabledByZenMode.onEach { sliderView.isEnabled = !it }.launchIn(this)
- viewModel.state
- .onEach {
- sliderView.setModel(it, animation, isInitialUpdate)
- isInitialUpdate = false
- }
- .launchIn(this)
+@Composable
+private fun BoxScope.VolumeIcon(
+ drawable: Drawable,
+ isVisible: Boolean,
+ modifier: Modifier = Modifier,
+) {
+ AnimatedVisibility(
+ visible = isVisible,
+ enter = fadeIn(animationSpec = tween(durationMillis = 50)),
+ exit = fadeOut(animationSpec = tween(durationMillis = 50)),
+ modifier = modifier.align(Alignment.Center).size(40.dp).padding(10.dp),
+ ) {
+ Icon(painter = DrawablePainter(drawable), contentDescription = null)
}
+}
- @SuppressLint("UseCompatLoadingForDrawables")
- private fun Slider.setModel(
- model: VolumeDialogSliderStateModel,
- animation: SpringAnimation,
- isInitialUpdate: Boolean,
- ) {
- valueFrom = model.minValue
- animation.setMinValue(model.minValue)
- valueTo = model.maxValue
- animation.setMaxValue(model.maxValue)
- // coerce the current value to the new value range before animating it. This prevents
- // animating from the value that is outside of current [valueFrom, valueTo].
- value = value.coerceIn(valueFrom, valueTo)
- trackIconActiveStart = model.icon
- if (isInitialUpdate) {
- value = model.value
- } else {
- animation.animateToFinalPosition(model.value)
- }
+@OptIn(ExperimentalMaterial3Api::class)
+fun SliderState.setOnValueChangeListener(onValueChange: ((Float) -> Unit)?) {
+ with(javaClass.getDeclaredField("onValueChange")) {
+ val oldIsAccessible = isAccessible
+ AutoCloseable { isAccessible = oldIsAccessible }
+ .use {
+ isAccessible = true
+ set(this@setOnValueChangeListener, onValueChange)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
index 75d427acc05b..c66955a0c187 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
@@ -71,7 +71,6 @@ constructor(private val viewModel: VolumeDialogSlidersViewModel) {
viewsToAnimate: Array<View>,
) {
with(component.sliderViewBinder()) { bind(sliderContainer) }
- with(component.sliderHapticsViewBinder()) { bind(sliderContainer) }
with(component.overscrollViewBinder()) { bind(sliderContainer, viewsToAnimate) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/compose/VolumeDialogSliderTrack.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/compose/VolumeDialogSliderTrack.kt
new file mode 100644
index 000000000000..1dd9ddac79be
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/compose/VolumeDialogSliderTrack.kt
@@ -0,0 +1,347 @@
+/*
+ * 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.volume.dialog.sliders.ui.compose
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.SliderColors
+import androidx.compose.material3.SliderDefaults
+import androidx.compose.material3.SliderState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasurePolicy
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.layout.layoutId
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastFilter
+import androidx.compose.ui.util.fastFirst
+import kotlin.math.min
+
+@Composable
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+fun VolumeDialogSliderTrack(
+ sliderState: SliderState,
+ colors: SliderColors,
+ isEnabled: Boolean,
+ modifier: Modifier = Modifier,
+ thumbTrackGapSize: Dp = 6.dp,
+ trackCornerSize: Dp = 12.dp,
+ trackInsideCornerSize: Dp = 2.dp,
+ trackSize: Dp = 40.dp,
+ activeTrackStartIcon: (@Composable BoxScope.(iconsState: SliderIconsState) -> Unit)? = null,
+ activeTrackEndIcon: (@Composable BoxScope.(iconsState: SliderIconsState) -> Unit)? = null,
+ inactiveTrackStartIcon: (@Composable BoxScope.(iconsState: SliderIconsState) -> Unit)? = null,
+ inactiveTrackEndIcon: (@Composable BoxScope.(iconsState: SliderIconsState) -> Unit)? = null,
+) {
+ val measurePolicy = remember(sliderState) { TrackMeasurePolicy(sliderState) }
+ Layout(
+ measurePolicy = measurePolicy,
+ content = {
+ SliderDefaults.Track(
+ sliderState = sliderState,
+ colors = colors,
+ enabled = isEnabled,
+ trackCornerSize = trackCornerSize,
+ trackInsideCornerSize = trackInsideCornerSize,
+ drawStopIndicator = null,
+ thumbTrackGapSize = thumbTrackGapSize,
+ drawTick = { _, _ -> },
+ modifier = Modifier.width(trackSize).layoutId(Contents.Track),
+ )
+
+ TrackIcon(
+ icon = activeTrackStartIcon,
+ contentsId = Contents.Active.TrackStartIcon,
+ isEnabled = isEnabled,
+ colors = colors,
+ state = measurePolicy,
+ )
+ TrackIcon(
+ icon = activeTrackEndIcon,
+ contentsId = Contents.Active.TrackEndIcon,
+ isEnabled = isEnabled,
+ colors = colors,
+ state = measurePolicy,
+ )
+ TrackIcon(
+ icon = inactiveTrackStartIcon,
+ contentsId = Contents.Inactive.TrackStartIcon,
+ isEnabled = isEnabled,
+ colors = colors,
+ state = measurePolicy,
+ )
+ TrackIcon(
+ icon = inactiveTrackEndIcon,
+ contentsId = Contents.Inactive.TrackEndIcon,
+ isEnabled = isEnabled,
+ colors = colors,
+ state = measurePolicy,
+ )
+ },
+ modifier = modifier,
+ )
+}
+
+@Composable
+private fun TrackIcon(
+ icon: (@Composable BoxScope.(sliderIconsState: SliderIconsState) -> Unit)?,
+ isEnabled: Boolean,
+ contentsId: Contents,
+ state: SliderIconsState,
+ colors: SliderColors,
+ modifier: Modifier = Modifier,
+) {
+ icon ?: return
+ Box(modifier = modifier.layoutId(contentsId).fillMaxSize()) {
+ CompositionLocalProvider(
+ LocalContentColor provides contentsId.getColor(colors, isEnabled)
+ ) {
+ icon(state)
+ }
+ }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+private class TrackMeasurePolicy(private val sliderState: SliderState) :
+ MeasurePolicy, SliderIconsState {
+
+ private val isVisible: Map<Contents, MutableState<Boolean>> =
+ mutableMapOf(
+ Contents.Active.TrackStartIcon to mutableStateOf(false),
+ Contents.Active.TrackEndIcon to mutableStateOf(false),
+ Contents.Inactive.TrackStartIcon to mutableStateOf(false),
+ Contents.Inactive.TrackEndIcon to mutableStateOf(false),
+ )
+
+ override val isActiveTrackStartIconVisible: Boolean
+ get() = isVisible.getValue(Contents.Active.TrackStartIcon).value
+
+ override val isActiveTrackEndIconVisible: Boolean
+ get() = isVisible.getValue(Contents.Active.TrackEndIcon).value
+
+ override val isInactiveTrackStartIconVisible: Boolean
+ get() = isVisible.getValue(Contents.Inactive.TrackStartIcon).value
+
+ override val isInactiveTrackEndIconVisible: Boolean
+ get() = isVisible.getValue(Contents.Inactive.TrackEndIcon).value
+
+ override fun MeasureScope.measure(
+ measurables: List<Measurable>,
+ constraints: Constraints,
+ ): MeasureResult {
+ val track = measurables.fastFirst { it.layoutId == Contents.Track }.measure(constraints)
+
+ val iconSize = min(track.width, track.height)
+ val iconConstraints = constraints.copy(maxWidth = iconSize, maxHeight = iconSize)
+
+ val icons =
+ measurables
+ .fastFilter { it.layoutId != Contents.Track }
+ .associateBy(
+ keySelector = { it.layoutId as Contents },
+ valueTransform = { it.measure(iconConstraints) },
+ )
+
+ return layout(track.width, track.height) {
+ with(Contents.Track) {
+ performPlacing(
+ placeable = track,
+ width = track.width,
+ height = track.height,
+ sliderState = sliderState,
+ )
+ }
+
+ for (iconLayoutId in icons.keys) {
+ with(iconLayoutId) {
+ performPlacing(
+ placeable = icons.getValue(iconLayoutId),
+ width = track.width,
+ height = track.height,
+ sliderState = sliderState,
+ )
+
+ isVisible.getValue(iconLayoutId).value =
+ isVisible(
+ placeable = icons.getValue(iconLayoutId),
+ width = track.width,
+ height = track.height,
+ sliderState = sliderState,
+ )
+ }
+ }
+ }
+ }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+private sealed interface Contents {
+
+ data object Track : Contents {
+ override fun Placeable.PlacementScope.performPlacing(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ) = placeable.place(x = 0, y = 0)
+
+ override fun isVisible(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ) = true
+
+ override fun getColor(sliderColors: SliderColors, isEnabled: Boolean): Color =
+ error("Unsupported")
+ }
+
+ interface Active : Contents {
+ override fun getColor(sliderColors: SliderColors, isEnabled: Boolean): Color {
+ return if (isEnabled) {
+ sliderColors.activeTickColor
+ } else {
+ sliderColors.disabledActiveTickColor
+ }
+ }
+
+ data object TrackStartIcon : Active {
+ override fun Placeable.PlacementScope.performPlacing(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ) =
+ placeable.place(
+ x = 0,
+ y = (height * (1 - sliderState.coercedValueAsFraction)).toInt(),
+ )
+
+ override fun isVisible(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ): Boolean = (height * (sliderState.coercedValueAsFraction)).toInt() > placeable.height
+ }
+
+ data object TrackEndIcon : Active {
+ override fun Placeable.PlacementScope.performPlacing(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ) = placeable.place(x = 0, y = (height - placeable.height))
+
+ override fun isVisible(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ): Boolean = (height * (sliderState.coercedValueAsFraction)).toInt() > placeable.height
+ }
+ }
+
+ interface Inactive : Contents {
+
+ override fun getColor(sliderColors: SliderColors, isEnabled: Boolean): Color {
+ return if (isEnabled) {
+ sliderColors.inactiveTickColor
+ } else {
+ sliderColors.disabledInactiveTickColor
+ }
+ }
+
+ data object TrackStartIcon : Inactive {
+ override fun Placeable.PlacementScope.performPlacing(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ) {
+ placeable.place(x = 0, y = 0)
+ }
+
+ override fun isVisible(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ): Boolean =
+ (height * (1 - sliderState.coercedValueAsFraction)).toInt() > placeable.height
+ }
+
+ data object TrackEndIcon : Inactive {
+ override fun Placeable.PlacementScope.performPlacing(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ) {
+ placeable.place(
+ x = 0,
+ y =
+ (height * (1 - sliderState.coercedValueAsFraction)).toInt() -
+ placeable.height,
+ )
+ }
+
+ override fun isVisible(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ ): Boolean =
+ (height * (1 - sliderState.coercedValueAsFraction)).toInt() > placeable.height
+ }
+ }
+
+ fun Placeable.PlacementScope.performPlacing(
+ placeable: Placeable,
+ width: Int,
+ height: Int,
+ sliderState: SliderState,
+ )
+
+ fun isVisible(placeable: Placeable, width: Int, height: Int, sliderState: SliderState): Boolean
+
+ fun getColor(sliderColors: SliderColors, isEnabled: Boolean): Color
+}
+
+/** Provides visibility state for each of the Slider's icons. */
+interface SliderIconsState {
+ val isActiveTrackStartIconVisible: Boolean
+ val isActiveTrackEndIconVisible: Boolean
+ val isInactiveTrackStartIconVisible: Boolean
+ val isInactiveTrackEndIconVisible: Boolean
+}
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 0d41860d9f57..0fdf5d6266d0 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
@@ -95,18 +95,17 @@ constructor(
private fun overscrollEvents(direction: Float): Flow<OverscrollEventModel> {
var startPosition: Float? = null
return inputEventsInteractor.event
- .mapNotNull { (it as? SliderInputEvent.Touch)?.event }
+ .mapNotNull { it as? SliderInputEvent.Touch }
.transform { touchEvent ->
// Skip events from inside the slider bounds for the case when the user adjusts
- // slider
- // towards max when the slider is already on max value.
- if (touchEvent.isFinalEvent()) {
+ // slider towards max when the slider is already on max value.
+ if (touchEvent is SliderInputEvent.Touch.End) {
startPosition = null
emit(OverscrollEventModel.Animate(0f))
return@transform
}
val currentStartPosition = startPosition
- val newPosition: Float = touchEvent.rawY
+ val newPosition: Float = touchEvent.y
if (currentStartPosition == null) {
startPosition = newPosition
} else {
@@ -126,11 +125,6 @@ constructor(
}
}
- /** @return true when the [MotionEvent] indicates the end of the gesture. */
- private fun MotionEvent.isFinalEvent(): Boolean {
- return actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL
- }
-
/** Models overscroll event */
sealed interface OverscrollEventModel {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModel.kt
deleted file mode 100644
index 755776ac9723..000000000000
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModel.kt
+++ /dev/null
@@ -1,43 +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.volume.dialog.sliders.ui.viewmodel
-
-import android.view.MotionEvent
-import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
-import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
-import com.android.systemui.volume.dialog.sliders.domain.interactor.VolumeDialogSliderInputEventsInteractor
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.stateIn
-
-@VolumeDialogSliderScope
-class VolumeDialogSliderInputEventsViewModel
-@Inject
-constructor(
- @VolumeDialog private val coroutineScope: CoroutineScope,
- private val interactor: VolumeDialogSliderInputEventsInteractor,
-) {
-
- val event =
- interactor.event.stateIn(coroutineScope, SharingStarted.Eagerly, null).filterNotNull()
-
- fun onTouchEvent(event: MotionEvent) {
- interactor.onTouchEvent(event)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt
index 8df9e788905c..b01046b377b0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt
@@ -20,17 +20,20 @@ import android.graphics.drawable.Drawable
import com.android.systemui.volume.dialog.shared.model.VolumeDialogStreamModel
data class VolumeDialogSliderStateModel(
- val minValue: Float,
- val maxValue: Float,
val value: Float,
+ val isDisabled: Boolean,
+ val valueRange: ClosedFloatingPointRange<Float>,
val icon: Drawable,
)
-fun VolumeDialogStreamModel.toStateModel(icon: Drawable): VolumeDialogSliderStateModel {
+fun VolumeDialogStreamModel.toStateModel(
+ isDisabled: Boolean,
+ icon: Drawable,
+): VolumeDialogSliderStateModel {
return VolumeDialogSliderStateModel(
- minValue = levelMin.toFloat(),
value = level.toFloat(),
- maxValue = levelMax.toFloat(),
+ isDisabled = isDisabled,
+ valueRange = levelMin.toFloat()..levelMax.toFloat(),
icon = icon,
)
}
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 a752f1f78e74..e89d5ab53560 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
@@ -16,6 +16,9 @@
package com.android.systemui.volume.dialog.sliders.ui.viewmodel
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.pointer.PointerEvent
+import androidx.compose.ui.input.pointer.PointerEventType
import com.android.systemui.util.time.SystemClock
import com.android.systemui.volume.Events
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
@@ -23,20 +26,23 @@ import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibili
import com.android.systemui.volume.dialog.shared.VolumeDialogLogger
import com.android.systemui.volume.dialog.shared.model.VolumeDialogStreamModel
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
+import com.android.systemui.volume.dialog.sliders.domain.interactor.VolumeDialogSliderInputEventsInteractor
import com.android.systemui.volume.dialog.sliders.domain.interactor.VolumeDialogSliderInteractor
import com.android.systemui.volume.dialog.sliders.domain.model.VolumeDialogSliderType
+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
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
@@ -62,6 +68,7 @@ constructor(
private val visibilityInteractor: VolumeDialogVisibilityInteractor,
@VolumeDialog private val coroutineScope: CoroutineScope,
private val volumeDialogSliderIconProvider: VolumeDialogSliderIconProvider,
+ private val inputEventsInteractor: VolumeDialogSliderInputEventsInteractor,
private val systemClock: SystemClock,
private val logger: VolumeDialogLogger,
) {
@@ -77,11 +84,12 @@ constructor(
.stateIn(coroutineScope, SharingStarted.Eagerly, null)
.filterNotNull()
- val isDisabledByZenMode: Flow<Boolean> = interactor.isDisabledByZenMode
val state: Flow<VolumeDialogSliderStateModel> =
- model
- .flatMapLatest { streamModel ->
- with(streamModel) {
+ combine(
+ interactor.isDisabledByZenMode,
+ model,
+ model.flatMapLatest { streamModel ->
+ with(streamModel) {
val isMuted = muteSupported && muted
when (sliderType) {
is VolumeDialogSliderType.Stream ->
@@ -101,7 +109,9 @@ constructor(
}
}
}
- .map { icon -> streamModel.toStateModel(icon) }
+ },
+ ) { isDisabledByZenMode, model, icon ->
+ model.toStateModel(icon = icon, isDisabled = isDisabledByZenMode)
}
.stateIn(coroutineScope, SharingStarted.Eagerly, null)
.filterNotNull()
@@ -116,11 +126,14 @@ constructor(
.launchIn(coroutineScope)
}
- fun setStreamVolume(volume: Int, fromUser: Boolean) {
+ fun setStreamVolume(volume: Float, fromUser: Boolean) {
if (fromUser) {
visibilityInteractor.resetDismissTimeout()
userVolumeUpdates.value =
- VolumeUpdate(newVolumeLevel = volume, timestampMillis = getTimestampMillis())
+ VolumeUpdate(
+ newVolumeLevel = volume.roundToInt(),
+ timestampMillis = getTimestampMillis(),
+ )
}
}
@@ -128,6 +141,28 @@ constructor(
logger.onVolumeSliderAdjustmentFinished(volume = volume, stream = sliderType.audioStream)
}
+ fun onTouchEvent(pointerEvent: PointerEvent) {
+ val position: Offset = pointerEvent.changes.first().position
+ when (pointerEvent.type) {
+ PointerEventType.Press ->
+ inputEventsInteractor.onTouchEvent(
+ SliderInputEvent.Touch.Start(position.x, position.y)
+ )
+ PointerEventType.Move ->
+ inputEventsInteractor.onTouchEvent(
+ SliderInputEvent.Touch.Move(position.x, position.y)
+ )
+ PointerEventType.Scroll ->
+ inputEventsInteractor.onTouchEvent(
+ SliderInputEvent.Touch.Move(position.x, position.y)
+ )
+ PointerEventType.Release ->
+ inputEventsInteractor.onTouchEvent(
+ SliderInputEvent.Touch.End(position.x, position.y)
+ )
+ }
+ }
+
private fun getTimestampMillis(): Long = systemClock.uptimeMillis()
private data class VolumeUpdate(val newVolumeLevel: Int, val timestampMillis: Long)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/haptics/ui/VolumeHapticsConfigsProvider.kt b/packages/SystemUI/src/com/android/systemui/volume/haptics/ui/VolumeHapticsConfigsProvider.kt
new file mode 100644
index 000000000000..92e9bf2d1ffc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/haptics/ui/VolumeHapticsConfigsProvider.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.volume.haptics.ui
+
+import com.android.systemui.haptics.slider.SeekableSliderTrackerConfig
+import com.android.systemui.haptics.slider.SliderHapticFeedbackConfig
+
+object VolumeHapticsConfigsProvider {
+
+ fun sliderHapticFeedbackConfig(
+ valueRange: ClosedFloatingPointRange<Float>
+ ): SliderHapticFeedbackConfig {
+ val sliderStepSize = 1f / (valueRange.endInclusive - valueRange.start)
+ return SliderHapticFeedbackConfig(
+ lowerBookendScale = 0.2f,
+ progressBasedDragMinScale = 0.2f,
+ progressBasedDragMaxScale = 0.5f,
+ deltaProgressForDragThreshold = 0f,
+ additionalVelocityMaxBump = 0.2f,
+ maxVelocityToScale = 0.1f, /* slider progress(from 0 to 1) per sec */
+ sliderStepSize = sliderStepSize,
+ )
+ }
+
+ val seekableSliderTrackerConfig =
+ SeekableSliderTrackerConfig(lowerBookendThreshold = 0f, upperBookendThreshold = 1f)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
index 8487ee751948..ec74f4f47bc9 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
@@ -36,4 +36,5 @@ class NoopWallpaperRepository @Inject constructor() : WallpaperRepository {
override val wallpaperInfo: StateFlow<WallpaperInfo?> = MutableStateFlow(null).asStateFlow()
override val wallpaperSupportsAmbientMode = flowOf(false)
override var rootView: View? = null
+ override val shouldSendFocalArea: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
index ed43f8323c31..9794c619041e 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
@@ -31,7 +31,6 @@ import com.android.systemui.Flags
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.shared.Flags.ambientAod
import com.android.systemui.user.data.model.SelectedUserModel
@@ -45,6 +44,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
@@ -65,6 +65,9 @@ interface WallpaperRepository {
/** Set rootView to get its windowToken afterwards */
var rootView: View?
+
+ /** when we use magic portrait wallpapers, we should always get its bounds from keyguard */
+ val shouldSendFocalArea: StateFlow<Boolean>
}
@SysUISingleton
@@ -76,7 +79,6 @@ constructor(
broadcastDispatcher: BroadcastDispatcher,
userRepository: UserRepository,
keyguardRepository: KeyguardRepository,
- keyguardClockRepository: KeyguardClockRepository,
private val wallpaperManager: WallpaperManager,
context: Context,
) : WallpaperRepository {
@@ -97,27 +99,7 @@ constructor(
// Only update the wallpaper status once the user selection has finished.
.filter { it.selectionStatus == SelectionStatus.SELECTION_COMPLETE }
- /** The bottom of notification stack respect to the top of screen. */
- private val notificationStackAbsoluteBottom: StateFlow<Float> =
- keyguardRepository.notificationStackAbsoluteBottom
-
- /** The top of shortcut respect to the top of screen. */
- private val shortcutAbsoluteTop: StateFlow<Float> = keyguardRepository.shortcutAbsoluteTop
-
- /**
- * The top of notification stack to give a default state of lockscreen remaining space for
- * states with notifications to compare with. It's the bottom of smartspace date and weather
- * smartspace in small clock state, plus proper bottom margin.
- */
- private val notificationStackDefaultTop = keyguardClockRepository.notificationDefaultTop
@VisibleForTesting var sendLockscreenLayoutJob: Job? = null
- private val lockscreenRemainingSpaceWithNotification: Flow<Triple<Float, Float, Float>> =
- combine(
- notificationStackAbsoluteBottom,
- notificationStackDefaultTop,
- shortcutAbsoluteTop,
- ::Triple,
- )
override val wallpaperInfo: StateFlow<WallpaperInfo?> =
if (!wallpaperManager.isWallpaperSupported) {
@@ -140,15 +122,16 @@ constructor(
override var rootView: View? = null
- val shouldSendNotificationLayout =
+ override val shouldSendFocalArea =
wallpaperInfo
.map {
- val shouldSendNotificationLayout = shouldSendNotificationLayout(it)
+ val shouldSendNotificationLayout =
+ it?.component?.className == MAGIC_PORTRAIT_CLASSNAME
if (shouldSendNotificationLayout) {
sendLockscreenLayoutJob =
scope.launch {
- lockscreenRemainingSpaceWithNotification.collect {
- (notificationBottom, notificationDefaultTop, shortcutTop) ->
+ keyguardRepository.wallpaperFocalAreaBounds.collect {
+ wallpaperFocalAreaBounds ->
wallpaperManager.sendWallpaperCommand(
/* windowToken = */ rootView?.windowToken,
/* action = */ WallpaperManager
@@ -157,14 +140,22 @@ constructor(
/* y = */ 0,
/* z = */ 0,
/* extras = */ Bundle().apply {
- putFloat("screenLeft", 0F)
- putFloat("smartspaceBottom", notificationDefaultTop)
- putFloat("notificationBottom", notificationBottom)
putFloat(
- "screenRight",
- context.resources.displayMetrics.widthPixels.toFloat(),
+ "wallpaperFocalAreaLeft",
+ wallpaperFocalAreaBounds.left,
+ )
+ putFloat(
+ "wallpaperFocalAreaRight",
+ wallpaperFocalAreaBounds.right,
+ )
+ putFloat(
+ "wallpaperFocalAreaTop",
+ wallpaperFocalAreaBounds.top,
+ )
+ putFloat(
+ "wallpaperFocalAreaBottom",
+ wallpaperFocalAreaBounds.bottom,
)
- putFloat("shortCutTop", shortcutTop)
},
)
}
@@ -176,10 +167,9 @@ constructor(
}
.stateIn(
scope,
- // Always be listening for wallpaper changes.
- if (Flags.magicPortraitWallpapers()) SharingStarted.Eagerly
- else SharingStarted.Lazily,
- initialValue = false,
+ // Always be listening for wallpaper changes when magic portrait flag is on
+ if (Flags.magicPortraitWallpapers()) SharingStarted.Eagerly else WhileSubscribed(),
+ initialValue = Flags.magicPortraitWallpapers(),
)
private suspend fun getWallpaper(selectedUser: SelectedUserModel): WallpaperInfo? {
@@ -188,14 +178,6 @@ constructor(
}
}
- private fun shouldSendNotificationLayout(wallpaperInfo: WallpaperInfo?): Boolean {
- return if (wallpaperInfo != null && wallpaperInfo.component != null) {
- wallpaperInfo.component!!.className == MAGIC_PORTRAIT_CLASSNAME
- } else {
- false
- }
- }
-
companion object {
const val MAGIC_PORTRAIT_CLASSNAME =
"com.google.android.apps.magicportrait.service.MagicPortraitWallpaperService"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
index 21519b0cb38a..ab691c630f97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
@@ -304,9 +304,7 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
testScope = TestScope(testDispatcher)
underTest =
KeyguardQuickAffordanceInteractor(
- keyguardInteractor =
- KeyguardInteractorFactory.create(featureFlags = featureFlags)
- .keyguardInteractor,
+ keyguardInteractor = kosmos.keyguardInteractor,
shadeInteractor = kosmos.shadeInteractor,
lockPatternUtils = lockPatternUtils,
keyguardStateController = keyguardStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index b5a227104900..051aba3d593f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -44,9 +44,10 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
@@ -191,9 +192,8 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
dockManager = DockManagerFake()
biometricSettingsRepository = FakeBiometricSettingsRepository()
- val withDeps = KeyguardInteractorFactory.create()
- keyguardInteractor = withDeps.keyguardInteractor
- repository = withDeps.repository
+ keyguardInteractor = kosmos.keyguardInteractor
+ repository = kosmos.fakeKeyguardRepository
whenever(userTracker.userHandle).thenReturn(mock())
whenever(lockPatternUtils.getStrongAuthForUser(ArgumentMatchers.anyInt()))
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 e68153ad2606..70450d29c74e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -57,7 +57,10 @@ import com.android.systemui.res.R
import com.android.systemui.settings.brightness.data.repository.BrightnessMirrorShowingRepository
import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
+import com.android.systemui.shade.data.repository.ShadeAnimationRepository
+import com.android.systemui.shade.data.repository.ShadeRepositoryImpl
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.statusbar.DragDownHelper
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -219,6 +222,10 @@ class NotificationShadeWindowViewControllerTest(flags: FlagsParameterization) :
notificationShadeDepthController,
view,
shadeViewController,
+ ShadeAnimationInteractorLegacyImpl(
+ ShadeAnimationRepository(),
+ ShadeRepositoryImpl(testScope),
+ ),
panelExpansionInteractor,
ShadeExpansionStateManager(),
stackScrollLayoutController,
@@ -521,6 +528,18 @@ class NotificationShadeWindowViewControllerTest(flags: FlagsParameterization) :
verify(view).findViewById<ViewGroup>(R.id.keyguard_message_area)
}
+ @EnableFlags(Flags.FLAG_SHADE_LAUNCH_ACCESSIBILITY)
+ @Test
+ fun notifiesTheViewWhenLaunchAnimationIsRunning() {
+ testScope.runTest {
+ underTest.setExpandAnimationRunning(true)
+ verify(view).setAnimatingContentLaunch(true)
+
+ underTest.setExpandAnimationRunning(false)
+ verify(view).setAnimatingContentLaunch(false)
+ }
+ }
+
@Test
@DisableSceneContainer
fun setsUpCommunalHubLayout_whenFlagEnabled() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index a02d333d1507..a7fe1ba76590 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -59,6 +59,7 @@ import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.DejankUtils;
+import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
@@ -71,6 +72,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
+import com.android.systemui.keyguard.ui.transitions.BlurConfig;
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
import com.android.systemui.kosmos.KosmosJavaAdapter;
@@ -110,6 +112,9 @@ import java.util.Map;
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
+// TODO(b/381263619) there are more changes and tweaks required to match the new bouncer/shade specs
+// Disabling for now but it will be fixed before the flag is fully ramped up.
+@DisableFlags(Flags.FLAG_BOUNCER_UI_REVAMP)
public class ScrimControllerTest extends SysuiTestCase {
@Rule public Expect mExpect = Expect.create();
@@ -286,7 +291,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mKeyguardTransitionInteractor,
mKeyguardInteractor,
mKosmos.getTestDispatcher(),
- mLinearLargeScreenShadeInterpolator);
+ mLinearLargeScreenShadeInterpolator,
+ new BlurConfig(0.0f, 0.0f));
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
@@ -1251,7 +1257,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mKeyguardTransitionInteractor,
mKeyguardInteractor,
mKosmos.getTestDispatcher(),
- mLinearLargeScreenShadeInterpolator);
+ mLinearLargeScreenShadeInterpolator,
+ new BlurConfig(0.0f, 0.0f));
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index fab7922f58e7..5d88f72b805b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -98,6 +98,7 @@ import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
@@ -2894,6 +2895,12 @@ public class BubblesTest extends SysuiTestCase {
@Override
public void animateBubbleBarLocation(BubbleBarLocation location) {
}
+
+ @Override
+ public void onDragItemOverBubbleBarDragZone(@NonNull BubbleBarLocation location) {}
+
+ @Override
+ public void onItemDraggedOutsideBubbleBarDropZone() {}
}
private static class FakeBubbleProperties implements BubbleProperties {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
index 0192fa47b434..739f6c2af2b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
@@ -79,7 +79,7 @@ var Kosmos.shortcutHelperInputShortcutsSource: KeyboardShortcutGroupsSource by
var Kosmos.shortcutHelperCurrentAppShortcutsSource: KeyboardShortcutGroupsSource by
Kosmos.Fixture { CurrentAppShortcutsSource(windowManager) }
-val Kosmos.shortcutHelperAccessibilityShortcutsSource: KeyboardShortcutGroupsSource by
+var Kosmos.shortcutHelperAccessibilityShortcutsSource: KeyboardShortcutGroupsSource by
Kosmos.Fixture { AccessibilityShortcutsSource(mainResources) }
val Kosmos.shortcutHelperExclusions by
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 8489d8380041..8ea80081a871 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.data.repository
import android.graphics.Point
+import android.graphics.RectF
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
@@ -129,6 +130,10 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
override val notificationStackAbsoluteBottom: StateFlow<Float>
get() = _notificationStackAbsoluteBottom.asStateFlow()
+ private val _wallpaperFocalAreaBounds = MutableStateFlow(RectF(0f, 0f, 0f, 0f))
+ override val wallpaperFocalAreaBounds: StateFlow<RectF>
+ get() = _wallpaperFocalAreaBounds.asStateFlow()
+
private val _isKeyguardEnabled = MutableStateFlow(true)
override val isKeyguardEnabled: StateFlow<Boolean> = _isKeyguardEnabled.asStateFlow()
@@ -287,6 +292,10 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
_notificationStackAbsoluteBottom.value = bottom
}
+ override fun setWallpaperFocalAreaBounds(bounds: RectF) {
+ _wallpaperFocalAreaBounds.value = bounds
+ }
+
override fun setCanIgnoreAuthAndReturnToGone(canWake: Boolean) {
_canIgnoreAuthAndReturnToGone.value = canWake
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractorKosmos.kt
new file mode 100644
index 000000000000..8fd6f62b315f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WallpaperFocalAreaInteractorKosmos.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import android.content.applicationContext
+import com.android.systemui.keyguard.data.repository.keyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
+import com.android.systemui.wallpapers.data.repository.wallpaperRepository
+
+val Kosmos.wallpaperFocalAreaInteractor by
+ Kosmos.Fixture {
+ WallpaperFocalAreaInteractor(
+ applicationScope = applicationCoroutineScope,
+ context = applicationContext,
+ keyguardRepository = keyguardRepository,
+ shadeRepository = shadeRepository,
+ activeNotificationsInteractor = activeNotificationsInteractor,
+ keyguardClockRepository = keyguardClockRepository,
+ wallpaperRepository = wallpaperRepository,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
index 40b8e0e62b03..37df05b68f9e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
@@ -20,6 +20,7 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.pulseExpansionInteractor
+import com.android.systemui.keyguard.domain.interactor.wallpaperFocalAreaInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -87,5 +88,6 @@ val Kosmos.keyguardRootViewModel by Fixture {
screenOffAnimationController = screenOffAnimationController,
aodBurnInViewModel = aodBurnInViewModel,
shadeInteractor = shadeInteractor,
+ wallpaperFocalAreaInteractor = wallpaperFocalAreaInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessKosmos.kt
index 4d1e0a8c025a..79167f840f60 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessKosmos.kt
@@ -16,9 +16,6 @@
package com.android.systemui.process
-import android.app.ActivityManager
-
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.mockito.mock
-val Kosmos.processWrapper: ProcessWrapperFake by Kosmos.Fixture { ProcessWrapperFake(mock<ActivityManager>()) }
+val Kosmos.processWrapper: ProcessWrapperFake by Kosmos.Fixture { ProcessWrapperFake() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessWrapperFake.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessWrapperFake.kt
index 152cc3019d85..dee3644e95bd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessWrapperFake.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/process/ProcessWrapperFake.kt
@@ -16,10 +16,9 @@
package com.android.systemui.process
-import android.app.ActivityManager
import android.os.UserHandle
-class ProcessWrapperFake(activityManager: ActivityManager) : ProcessWrapper(activityManager) {
+class ProcessWrapperFake : ProcessWrapper() {
var systemUser: Boolean = false
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java
index 6cd6594c3404..c6daed1aa58f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java
@@ -61,6 +61,7 @@ public class RankingBuilder {
private boolean mIsBubble = false;
private int mProposedImportance = IMPORTANCE_UNSPECIFIED;
private boolean mSensitiveContent = false;
+ private String mSummarization = null;
public RankingBuilder() {
}
@@ -92,6 +93,7 @@ public class RankingBuilder {
mIsBubble = ranking.isBubble();
mProposedImportance = ranking.getProposedImportance();
mSensitiveContent = ranking.hasSensitiveContent();
+ mSummarization = ranking.getSummarization();
}
public Ranking build() {
@@ -122,7 +124,8 @@ public class RankingBuilder {
mRankingAdjustment,
mIsBubble,
mProposedImportance,
- mSensitiveContent);
+ mSensitiveContent,
+ mSummarization);
return ranking;
}
@@ -262,6 +265,11 @@ public class RankingBuilder {
return this;
}
+ public RankingBuilder setSummarization(String summary) {
+ mSummarization = summary;
+ return this;
+ }
+
private static <E> ArrayList<E> copyList(List<E> list) {
if (list == null) {
return null;
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponentKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponentKosmos.kt
index 36fa82f82f0d..4ca044d60f3f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponentKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponentKosmos.kt
@@ -32,10 +32,8 @@ import com.android.systemui.volume.dialog.data.repository.volumeDialogVisibility
import com.android.systemui.volume.dialog.sliders.domain.model.VolumeDialogSliderType
import com.android.systemui.volume.dialog.sliders.domain.model.volumeDialogSliderType
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogOverscrollViewBinder
-import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderHapticsViewBinder
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderViewBinder
import com.android.systemui.volume.dialog.sliders.ui.volumeDialogOverscrollViewBinder
-import com.android.systemui.volume.dialog.sliders.ui.volumeDialogSliderHapticsViewBinder
import com.android.systemui.volume.dialog.sliders.ui.volumeDialogSliderViewBinder
import com.android.systemui.volume.mediaControllerRepository
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.mediaControllerInteractor
@@ -65,9 +63,6 @@ fun Kosmos.volumeDialogSliderComponent(type: VolumeDialogSliderType): VolumeDial
override fun sliderViewBinder(): VolumeDialogSliderViewBinder =
localKosmos.volumeDialogSliderViewBinder
- override fun sliderHapticsViewBinder(): VolumeDialogSliderHapticsViewBinder =
- localKosmos.volumeDialogSliderHapticsViewBinder
-
override fun overscrollViewBinder(): VolumeDialogOverscrollViewBinder =
localKosmos.volumeDialogOverscrollViewBinder
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinderKosmos.kt
deleted file mode 100644
index d6845b1ff7e3..000000000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderHapticsViewBinderKosmos.kt
+++ /dev/null
@@ -1,33 +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.volume.dialog.sliders.ui
-
-import com.android.systemui.haptics.msdl.msdlPlayer
-import com.android.systemui.haptics.vibratorHelper
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.time.systemClock
-import com.android.systemui.volume.dialog.sliders.ui.viewmodel.volumeDialogSliderInputEventsViewModel
-
-val Kosmos.volumeDialogSliderHapticsViewBinder by
- Kosmos.Fixture {
- VolumeDialogSliderHapticsViewBinder(
- volumeDialogSliderInputEventsViewModel,
- vibratorHelper,
- msdlPlayer,
- systemClock,
- )
- }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinderKosmos.kt
index c6db717e004f..484a7cc30152 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinderKosmos.kt
@@ -16,14 +16,16 @@
package com.android.systemui.volume.dialog.sliders.ui
+import com.android.systemui.haptics.slider.sliderHapticsViewModelFactory
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.volume.dialog.sliders.ui.viewmodel.volumeDialogSliderInputEventsViewModel
+import com.android.systemui.volume.dialog.sliders.ui.viewmodel.volumeDialogOverscrollViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.volumeDialogSliderViewModel
val Kosmos.volumeDialogSliderViewBinder by
Kosmos.Fixture {
VolumeDialogSliderViewBinder(
volumeDialogSliderViewModel,
- volumeDialogSliderInputEventsViewModel,
+ volumeDialogOverscrollViewModel,
+ sliderHapticsViewModelFactory,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModelKosmos.kt
deleted file mode 100644
index 2de0e8f76a4b..000000000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderInputEventsViewModelKosmos.kt
+++ /dev/null
@@ -1,29 +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.volume.dialog.sliders.ui.viewmodel
-
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.volume.dialog.sliders.domain.interactor.volumeDialogSliderInputEventsInteractor
-
-val Kosmos.volumeDialogSliderInputEventsViewModel by
- Kosmos.Fixture {
- VolumeDialogSliderInputEventsViewModel(
- applicationCoroutineScope,
- volumeDialogSliderInputEventsInteractor,
- )
- }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModelKosmos.kt
index b26081c40c38..90bbb28ff519 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModelKosmos.kt
@@ -21,6 +21,7 @@ import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.util.time.systemClock
import com.android.systemui.volume.dialog.domain.interactor.volumeDialogVisibilityInteractor
import com.android.systemui.volume.dialog.shared.volumeDialogLogger
+import com.android.systemui.volume.dialog.sliders.domain.interactor.volumeDialogSliderInputEventsInteractor
import com.android.systemui.volume.dialog.sliders.domain.interactor.volumeDialogSliderInteractor
import com.android.systemui.volume.dialog.sliders.domain.model.volumeDialogSliderType
@@ -29,6 +30,7 @@ val Kosmos.volumeDialogSliderViewModel by
VolumeDialogSliderViewModel(
sliderType = volumeDialogSliderType,
interactor = volumeDialogSliderInteractor,
+ inputEventsInteractor = volumeDialogSliderInputEventsInteractor,
visibilityInteractor = volumeDialogVisibilityInteractor,
coroutineScope = applicationCoroutineScope,
volumeDialogSliderIconProvider = volumeDialogSliderIconProvider,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt
index ddb9a3ffee6d..f0c0d30e6db4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt
@@ -19,7 +19,6 @@ package com.android.systemui.wallpapers.data.repository
import android.content.applicationContext
import com.android.app.wallpaperManager
import com.android.systemui.broadcast.broadcastDispatcher
-import com.android.systemui.keyguard.data.repository.keyguardClockRepository
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
@@ -34,8 +33,7 @@ val Kosmos.wallpaperRepository by Fixture {
bgDispatcher = testDispatcher,
broadcastDispatcher = broadcastDispatcher,
userRepository = userRepository,
- wallpaperManager = wallpaperManager,
- keyguardClockRepository = keyguardClockRepository,
keyguardRepository = keyguardRepository,
+ wallpaperManager = wallpaperManager,
)
}
diff --git a/ravenwood/scripts/pta-framework.sh b/ravenwood/scripts/pta-framework.sh
index 224ab59e2e09..46c2c01c8ee8 100755
--- a/ravenwood/scripts/pta-framework.sh
+++ b/ravenwood/scripts/pta-framework.sh
@@ -79,6 +79,7 @@ run_pta() {
$extra_args
if ! [[ -f $OUT_SCRIPT ]] ; then
+ echo "No files need updating."
# no operations generated.
exit 0
fi
@@ -88,4 +89,4 @@ run_pta() {
return 0
}
-run_pta "$extra_args" \ No newline at end of file
+run_pta "$extra_args"
diff --git a/ravenwood/texts/ravenwood-framework-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt
index 4033782c607e..fff9e6ad41d5 100644
--- a/ravenwood/texts/ravenwood-framework-policies.txt
+++ b/ravenwood/texts/ravenwood-framework-policies.txt
@@ -62,4 +62,4 @@ class android.text.ClipboardManager keep # no-pta
# Just enough to allow ResourcesManager to run
class android.hardware.display.DisplayManagerGlobal keep # no-pta
- method getInstance ()Landroid/hardware/display/DisplayManagerGlobal; ignore
+ method getInstance ()Landroid/hardware/display/DisplayManagerGlobal; ignore # no-pta
diff --git a/ravenwood/texts/ravenwood-standard-options.txt b/ravenwood/texts/ravenwood-standard-options.txt
index 27223d8b72ff..91fd9283aff2 100644
--- a/ravenwood/texts/ravenwood-standard-options.txt
+++ b/ravenwood/texts/ravenwood-standard-options.txt
@@ -31,6 +31,9 @@
--remove-annotation
android.ravenwood.annotation.RavenwoodRemove
+--ignore-annotation
+ android.ravenwood.annotation.RavenwoodIgnore
+
--substitute-annotation
android.ravenwood.annotation.RavenwoodReplace
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt
index 4a11259a8ef7..ef1cb5dfca89 100644
--- a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt
@@ -45,7 +45,8 @@ class Annotations {
"@android.ravenwood.annotation.RavenwoodRedirect"
FilterPolicy.Throw ->
"@android.ravenwood.annotation.RavenwoodThrow"
- FilterPolicy.Ignore -> null // Ignore has no annotation. (because it's not very safe.)
+ FilterPolicy.Ignore ->
+ "@android.ravenwood.annotation.RavenwoodIgnore"
FilterPolicy.Remove ->
"@android.ravenwood.annotation.RavenwoodRemove"
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 75c629b77700..fda57d6bb986 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -45,6 +45,7 @@ import android.view.MotionEvent.PointerProperties;
import android.view.accessibility.AccessibilityEvent;
import com.android.server.LocalServices;
+import com.android.server.accessibility.autoclick.AutoclickController;
import com.android.server.accessibility.gestures.TouchExplorer;
import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.FullScreenMagnificationGestureHandler;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 875b655fe3d2..91775f8eed96 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -5084,39 +5084,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final List<String> permittedServices = dpm.getPermittedAccessibilityServices(userId);
// permittedServices null means all accessibility services are allowed.
- boolean allowed = permittedServices == null || permittedServices.contains(packageName);
- if (allowed) {
- if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
- && android.security.Flags.extendEcmToAllSettings()) {
- try {
- final EnhancedConfirmationManager userContextEcm =
- mContext.createContextAsUser(UserHandle.of(userId), /* flags = */ 0)
- .getSystemService(EnhancedConfirmationManager.class);
- if (userContextEcm != null) {
- return !userContextEcm.isRestricted(packageName,
- AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
- }
- return false;
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(LOG_TAG, "Exception when retrieving package:" + packageName, e);
- return false;
- }
- } else {
- try {
- final int mode = mContext.getSystemService(AppOpsManager.class)
- .noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
- uid, packageName);
- final boolean ecmEnabled = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
- return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED
- || mode == AppOpsManager.MODE_DEFAULT;
- } catch (Exception e) {
- // Fallback in case if app ops is not available in testing.
- return false;
- }
- }
- }
- return false;
+ return permittedServices == null || permittedServices.contains(packageName);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
index 3415300ec8d1..1bc9c783df76 100644
--- a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.server.accessibility;
+package com.android.server.accessibility.autoclick;
import static android.view.MotionEvent.BUTTON_PRIMARY;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_DEFAULT;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT;
-import static com.android.server.accessibility.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME;
+import static com.android.server.accessibility.autoclick.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME;
import android.accessibilityservice.AccessibilityTrace;
import android.annotation.NonNull;
@@ -43,6 +43,9 @@ import android.view.WindowManager;
import androidx.annotation.VisibleForTesting;
import com.android.internal.accessibility.util.AccessibilityUtils;
+import com.android.server.accessibility.AccessibilityTraceManager;
+import com.android.server.accessibility.BaseEventStreamTransformation;
+import com.android.server.accessibility.Flags;
/**
* Implements "Automatically click on mouse stop" feature.
diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickIndicatorView.java
index 93ce1f044f0b..557e1b2afcd5 100644
--- a/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickIndicatorView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.accessibility;
+package com.android.server.accessibility.autoclick;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT;
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index a37b2b926c9c..02a8f6218468 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -612,7 +612,7 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public void enablePermissionsSync(int associationId) {
- if (UserHandle.getAppId(Binder.getCallingUid()) == SYSTEM_UID) {
+ if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) {
throw new SecurityException("Caller must be system UID");
}
mSystemDataTransferProcessor.enablePermissionsSync(associationId);
@@ -620,7 +620,7 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public void disablePermissionsSync(int associationId) {
- if (UserHandle.getAppId(Binder.getCallingUid()) == SYSTEM_UID) {
+ if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) {
throw new SecurityException("Caller must be system UID");
}
mSystemDataTransferProcessor.disablePermissionsSync(associationId);
@@ -628,7 +628,7 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public PermissionSyncRequest getPermissionSyncRequest(int associationId) {
- if (UserHandle.getAppId(Binder.getCallingUid()) == SYSTEM_UID) {
+ if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) {
throw new SecurityException("Caller must be system UID");
}
return mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
@@ -704,7 +704,7 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public byte[] getBackupPayload(int userId) {
- if (UserHandle.getAppId(Binder.getCallingUid()) == SYSTEM_UID) {
+ if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) {
throw new SecurityException("Caller must be system");
}
return mBackupRestoreProcessor.getBackupPayload(userId);
@@ -712,7 +712,7 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public void applyRestoredPayload(byte[] payload, int userId) {
- if (UserHandle.getAppId(Binder.getCallingUid()) == SYSTEM_UID) {
+ if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) {
throw new SecurityException("Caller must be system");
}
mBackupRestoreProcessor.applyRestoredPayload(payload, userId);
diff --git a/services/core/java/com/android/server/am/BroadcastController.java b/services/core/java/com/android/server/am/BroadcastController.java
index bfacfbba4e22..bec5db79ff9d 100644
--- a/services/core/java/com/android/server/am/BroadcastController.java
+++ b/services/core/java/com/android/server/am/BroadcastController.java
@@ -317,7 +317,7 @@ class BroadcastController {
Slog.w(TAG, "registerReceiverWithFeature: no app for " + caller);
return null;
}
- if (callerApp.info.uid != SYSTEM_UID
+ if (!UserHandle.isCore(callerApp.info.uid)
&& !callerApp.getPkgList().containsKey(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
+ " is not running in process " + callerApp);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 0b7890167c08..3817ba1a28b9 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -305,10 +305,6 @@ 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) {
@@ -327,12 +323,6 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
mAllowBgActivityStartsForActivitySender.remove(token);
mAllowBgActivityStartsForBroadcastSender.remove(token);
mAllowBgActivityStartsForServiceSender.remove(token);
- if (mAllowlistDuration != null) {
- mAllowlistDuration.remove(token);
- if (mAllowlistDuration.isEmpty()) {
- mAllowlistDuration = null;
- }
- }
}
public void registerCancelListenerLocked(IResultReceiver receiver) {
@@ -713,7 +703,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
return res;
}
- @VisibleForTesting BackgroundStartPrivileges getBackgroundStartPrivilegesForActivitySender(
+ private BackgroundStartPrivileges getBackgroundStartPrivilegesForActivitySender(
IBinder allowlistToken) {
return mAllowBgActivityStartsForActivitySender.contains(allowlistToken)
? BackgroundStartPrivileges.allowBackgroundActivityStarts(allowlistToken)
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 8e09e3b8e112..833599810210 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -604,7 +604,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */
+ /** Returned from {@link #verifyAndGetBypass(int, String, String, int, String, boolean)}. */
private static final class PackageVerificationResult {
final RestrictionBypass bypass;
@@ -3087,10 +3087,10 @@ public class AppOpsService extends IAppOpsService.Stub {
public int checkPackage(int uid, String packageName) {
Objects.requireNonNull(packageName);
try {
- verifyAndGetBypass(uid, packageName, null, null, true);
+ verifyAndGetBypass(uid, packageName, null, Process.INVALID_UID, null, true);
// When the caller is the system, it's possible that the packageName is the special
// one (e.g., "root") which isn't actually existed.
- if (resolveUid(packageName) == uid
+ if (resolveNonAppUid(packageName) == uid
|| (isPackageExisted(packageName)
&& !filterAppAccessUnlocked(packageName, UserHandle.getUserId(uid)))) {
return AppOpsManager.MODE_ALLOWED;
@@ -3306,7 +3306,7 @@ public class AppOpsService extends IAppOpsService.Stub {
boolean shouldCollectMessage, int notedCount) {
PackageVerificationResult pvr;
try {
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
@@ -3930,7 +3930,7 @@ public class AppOpsService extends IAppOpsService.Stub {
// Test if the proxied operation will succeed before starting the proxy operation
final SyncNotedAppOp testProxiedOp = startOperationDryRun(code,
proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag,
- proxiedVirtualDeviceId, resolvedProxyPackageName, proxiedFlags,
+ proxiedVirtualDeviceId, proxyUid, resolvedProxyPackageName, proxiedFlags,
startIfModeDefault);
if (!shouldStartForMode(testProxiedOp.getOpMode(), startIfModeDefault)) {
@@ -3970,7 +3970,7 @@ public class AppOpsService extends IAppOpsService.Stub {
int attributionChainId) {
PackageVerificationResult pvr;
try {
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
@@ -4097,11 +4097,11 @@ public class AppOpsService extends IAppOpsService.Stub {
*/
private SyncNotedAppOp startOperationDryRun(int code, int uid,
@NonNull String packageName, @Nullable String attributionTag, int virtualDeviceId,
- String proxyPackageName, @OpFlags int flags,
+ int proxyUid, String proxyPackageName, @OpFlags int flags,
boolean startIfModeDefault) {
PackageVerificationResult pvr;
try {
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
@@ -4656,13 +4656,17 @@ public class AppOpsService extends IAppOpsService.Stub {
private boolean isSpecialPackage(int callingUid, @Nullable String packageName) {
final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, packageName);
return callingUid == Process.SYSTEM_UID
- || resolveUid(resolvedPackage) != Process.INVALID_UID;
+ || resolveNonAppUid(resolvedPackage) != Process.INVALID_UID;
}
private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) {
if (attributionSource.getUid() != Binder.getCallingUid()
&& attributionSource.isTrusted(mContext)) {
- return true;
+ // if there is a next attribution source, it must be trusted, as well.
+ if (attributionSource.getNext() == null
+ || attributionSource.getNext().isTrusted(mContext)) {
+ return true;
+ }
}
return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), null)
@@ -4757,19 +4761,20 @@ public class AppOpsService extends IAppOpsService.Stub {
}
/**
- * @see #verifyAndGetBypass(int, String, String, String, boolean)
+ * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
*/
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
@Nullable String attributionTag) {
- return verifyAndGetBypass(uid, packageName, attributionTag, null);
+ return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null);
}
/**
- * @see #verifyAndGetBypass(int, String, String, String, boolean)
+ * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
*/
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
- @Nullable String attributionTag, @Nullable String proxyPackageName) {
- return verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName, false);
+ @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) {
+ return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
+ false);
}
/**
@@ -4780,14 +4785,15 @@ public class AppOpsService extends IAppOpsService.Stub {
* @param uid The uid the package belongs to
* @param packageName The package the might belong to the uid
* @param attributionTag attribution tag or {@code null} if no need to verify
- * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled
+ * @param proxyUid The proxy uid, from which the attribution tag is to be pulled
+ * @param proxyPackageName The proxy package, from which the attribution tag may be pulled
* @param suppressErrorLogs Whether to print to logcat about nonmatching parameters
*
* @return PackageVerificationResult containing {@link RestrictionBypass} and whether the
* attribution tag is valid
*/
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
- @Nullable String attributionTag, @Nullable String proxyPackageName,
+ @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName,
boolean suppressErrorLogs) {
if (uid == Process.ROOT_UID) {
// For backwards compatibility, don't check package name for root UID.
@@ -4831,34 +4837,47 @@ public class AppOpsService extends IAppOpsService.Stub {
int callingUid = Binder.getCallingUid();
- // Allow any attribution tag for resolvable uids
- int pkgUid;
+ // Allow any attribution tag for resolvable, non-app uids
+ int nonAppUid;
if (Objects.equals(packageName, "com.android.shell")) {
// Special case for the shell which is a package but should be able
// to bypass app attribution tag restrictions.
- pkgUid = Process.SHELL_UID;
+ nonAppUid = Process.SHELL_UID;
} else {
- pkgUid = resolveUid(packageName);
+ nonAppUid = resolveNonAppUid(packageName);
}
- if (pkgUid != Process.INVALID_UID) {
- if (pkgUid != UserHandle.getAppId(uid)) {
+ if (nonAppUid != Process.INVALID_UID) {
+ if (nonAppUid != UserHandle.getAppId(uid)) {
if (!suppressErrorLogs) {
Slog.e(TAG, "Bad call made by uid " + callingUid + ". "
- + "Package \"" + packageName + "\" does not belong to uid " + uid
- + ".");
+ + "Package \"" + packageName + "\" does not belong to uid " + uid
+ + ".");
+ }
+ String otherUidMessage =
+ DEBUG ? " but it is really " + nonAppUid : " but it is not";
+ throw new SecurityException("Specified package \"" + packageName
+ + "\" under uid " + UserHandle.getAppId(uid) + otherUidMessage);
+ }
+ // We only allow bypassing the attribution tag verification if the proxy is a
+ // system app (or is null), in order to prevent abusive apps clogging the appops
+ // system with unlimited attribution tags via proxy calls.
+ boolean proxyIsSystemAppOrNull = true;
+ if (proxyPackageName != null) {
+ int proxyAppId = UserHandle.getAppId(proxyUid);
+ if (proxyAppId >= Process.FIRST_APPLICATION_UID) {
+ proxyIsSystemAppOrNull =
+ mPackageManagerInternal.isSystemPackage(proxyPackageName);
}
- String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
- throw new SecurityException("Specified package \"" + packageName + "\" under uid "
- + UserHandle.getAppId(uid) + otherUidMessage);
}
return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
- /* isAttributionTagValid */ true);
+ /* isAttributionTagValid */ proxyIsSystemAppOrNull);
}
int userId = UserHandle.getUserId(uid);
RestrictionBypass bypass = null;
boolean isAttributionTagValid = false;
+ int pkgUid = nonAppUid;
final long ident = Binder.clearCallingIdentity();
try {
PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
@@ -5649,7 +5668,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (nonpackageUid != -1) {
packageName = null;
} else {
- packageUid = resolveUid(packageName);
+ packageUid = resolveNonAppUid(packageName);
if (packageUid < 0) {
packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
@@ -6749,7 +6768,13 @@ public class AppOpsService extends IAppOpsService.Stub {
if (restricted && attrOp.isRunning()) {
attrOp.pause();
} else if (attrOp.isPaused()) {
- attrOp.resume();
+ RestrictionBypass bypass = verifyAndGetBypass(uid, ops.packageName, attrOp.tag)
+ .bypass;
+ if (!isOpRestrictedLocked(uid, code, ops.packageName, attrOp.tag,
+ Context.DEVICE_ID_DEFAULT, bypass, false)) {
+ // Only resume if there are no other restrictions remaining on this op
+ attrOp.resume();
+ }
}
}
}
@@ -7198,7 +7223,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- private static int resolveUid(String packageName) {
+ private static int resolveNonAppUid(String packageName) {
if (packageName == null) {
return Process.INVALID_UID;
}
diff --git a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
index 030ce12f5063..fece7a899f0a 100644
--- a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
+++ b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
@@ -65,6 +65,12 @@ class AudioManagerShellCommand extends ShellCommand {
return setRingerMode();
case "set-volume":
return setVolume();
+ case "get-min-volume":
+ return getMinVolume();
+ case "get-max-volume":
+ return getMaxVolume();
+ case "get-stream-volume":
+ return getStreamVolume();
case "set-device-volume":
return setDeviceVolume();
case "adj-mute":
@@ -106,6 +112,12 @@ class AudioManagerShellCommand extends ShellCommand {
pw.println(" Sets the Ringer mode to one of NORMAL|SILENT|VIBRATE");
pw.println(" set-volume STREAM_TYPE VOLUME_INDEX");
pw.println(" Sets the volume for STREAM_TYPE to VOLUME_INDEX");
+ pw.println(" get-min-volume STREAM_TYPE");
+ pw.println(" Gets the min volume for STREAM_TYPE");
+ pw.println(" get-max-volume STREAM_TYPE");
+ pw.println(" Gets the max volume for STREAM_TYPE");
+ pw.println(" get-stream-volume STREAM_TYPE");
+ pw.println(" Gets the volume for STREAM_TYPE");
pw.println(" set-device-volume STREAM_TYPE VOLUME_INDEX NATIVE_DEVICE_TYPE");
pw.println(" Sets for NATIVE_DEVICE_TYPE the STREAM_TYPE volume to VOLUME_INDEX");
pw.println(" adj-mute STREAM_TYPE");
@@ -296,6 +308,33 @@ class AudioManagerShellCommand extends ShellCommand {
return 0;
}
+ private int getMinVolume() {
+ final Context context = mService.mContext;
+ final AudioManager am = context.getSystemService(AudioManager.class);
+ final int stream = readIntArg();
+ final int result = am.getStreamMinVolume(stream);
+ getOutPrintWriter().println("AudioManager.getStreamMinVolume(" + stream + ") -> " + result);
+ return 0;
+ }
+
+ private int getMaxVolume() {
+ final Context context = mService.mContext;
+ final AudioManager am = context.getSystemService(AudioManager.class);
+ final int stream = readIntArg();
+ final int result = am.getStreamMaxVolume(stream);
+ getOutPrintWriter().println("AudioManager.getStreamMaxVolume(" + stream + ") -> " + result);
+ return 0;
+ }
+
+ private int getStreamVolume() {
+ final Context context = mService.mContext;
+ final AudioManager am = context.getSystemService(AudioManager.class);
+ final int stream = readIntArg();
+ final int result = am.getStreamVolume(stream);
+ getOutPrintWriter().println("AudioManager.getStreamVolume(" + stream + ") -> " + result);
+ return 0;
+ }
+
private int setDeviceVolume() {
final Context context = mService.mContext;
final AudioDeviceVolumeManager advm = (AudioDeviceVolumeManager) context.getSystemService(
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 709c13bc9704..320dd8f188c0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -47,9 +47,10 @@ import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
import static android.media.AudioManager.STREAM_SYSTEM;
-import static android.media.IAudioManagerNative.HardeningType;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
+import static android.media.audio.Flags.cacheGetStreamMinMaxVolume;
+import static android.media.audio.Flags.cacheGetStreamVolume;
import static android.media.audio.Flags.concurrentAudioRecordBypassPermission;
import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency;
import static android.media.audio.Flags.focusFreezeTestApi;
@@ -898,6 +899,16 @@ public class AudioService extends IAudioService.Stub
public void permissionUpdateBarrier() {
AudioService.this.permissionUpdateBarrier();
}
+
+ /**
+ * Update mute state event for port
+ * @param portId Port id to update
+ * @param event the mute event containing info about the mute
+ */
+ @Override
+ public void portMuteEvent(int portId, int event) {
+ mPlaybackMonitor.portMuteEvent(portId, event, Binder.getCallingUid());
+ }
};
// List of binder death handlers for setMode() client processes.
@@ -1900,6 +1911,12 @@ public class AudioService extends IAudioService.Stub
mSpatializerHelper.onRoutingUpdated();
}
checkMuteAwaitConnection();
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after routing update");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
//-----------------------------------------------------------------
@@ -4976,6 +4993,10 @@ public class AudioService extends IAudioService.Stub
+ ringMyCar());
pw.println("\tandroid.media.audio.Flags.concurrentAudioRecordBypassPermission:"
+ concurrentAudioRecordBypassPermission());
+ pw.println("\tandroid.media.audio.Flags.cacheGetStreamMinMaxVolume:"
+ + cacheGetStreamMinMaxVolume());
+ pw.println("\tandroid.media.audio.Flags.cacheGetStreamVolume:"
+ + cacheGetStreamVolume());
}
private void dumpAudioMode(PrintWriter pw) {
@@ -7042,6 +7063,13 @@ public class AudioService extends IAudioService.Stub
streamState.mIsMuted = false;
}
}
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG,
+ "Clear volume cache after possibly changing mute in readAudioSettings");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
readVolumeGroupsSettings(userSwitch);
@@ -9262,11 +9290,23 @@ public class AudioService extends IAudioService.Stub
public void put(int key, int value) {
super.put(key, value);
record("put", key, value);
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after update index map");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
@Override
public void setValueAt(int index, int value) {
super.setValueAt(index, value);
record("setValueAt", keyAt(index), value);
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after update index map");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
// Record all changes in the VolumeStreamState
@@ -9366,6 +9406,12 @@ public class AudioService extends IAudioService.Stub
mIndexMinNoPerm = mIndexMin;
}
}
+ if (cacheGetStreamMinMaxVolume() && mStreamType == AudioSystem.STREAM_VOICE_CALL) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear min volume cache from updateIndexFactors");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_MIN_CACHING_API);
+ }
final int status = AudioSystem.initStreamVolume(
mStreamType, indexMinVolCurve, indexMaxVolCurve);
@@ -9403,11 +9449,19 @@ public class AudioService extends IAudioService.Stub
* @param index minimum index expressed in "UI units", i.e. no 10x factor
*/
public void updateNoPermMinIndex(int index) {
+ boolean changedNoPermMinIndex =
+ cacheGetStreamMinMaxVolume() && (index * 10) != mIndexMinNoPerm;
mIndexMinNoPerm = index * 10;
if (mIndexMinNoPerm < mIndexMin) {
Log.e(TAG, "Invalid mIndexMinNoPerm for stream " + mStreamType);
mIndexMinNoPerm = mIndexMin;
}
+ if (changedNoPermMinIndex) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear min volume cache from updateNoPermMinIndex");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_MIN_CACHING_API);
+ }
}
/**
@@ -9982,8 +10036,9 @@ public class AudioService extends IAudioService.Stub
* @return true if the mute state was changed
*/
public boolean mute(boolean state, boolean apply, String src) {
+ boolean changed;
synchronized (VolumeStreamState.class) {
- boolean changed = state != mIsMuted;
+ changed = state != mIsMuted;
if (changed) {
sMuteLogger.enqueue(
new AudioServiceEvents.StreamMuteEvent(mStreamType, state, src));
@@ -10001,8 +10056,16 @@ public class AudioService extends IAudioService.Stub
doMute();
}
}
- return changed;
}
+
+ if (cacheGetStreamVolume() && changed) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after changing mute state");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
+
+ return changed;
}
public void doMute() {
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index e2e06b63c7d6..57b5febf4df0 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -435,6 +435,49 @@ public final class PlaybackActivityMonitor
/**
* Update event for port
* @param portId Port id to update
+ * @param event the mute event containing info about the mute
+ * @param binderUid Calling binder uid
+ */
+ public void portMuteEvent(int portId, @PlayerMuteEvent int event, int binderUid) {
+ if (!UserHandle.isCore(binderUid)) {
+ Log.e(TAG, "Forbidden operation from uid " + binderUid);
+ return;
+ }
+
+ synchronized (mPlayerLock) {
+ int piid;
+ if (portToPiidSimplification()) {
+ int idxOfPiid = mPiidToPortId.indexOfValue(portId);
+ if (idxOfPiid < 0) {
+ Log.w(TAG, "No piid assigned for invalid/internal port id " + portId);
+ return;
+ }
+ piid = mPiidToPortId.keyAt(idxOfPiid);
+ } else {
+ piid = mPortIdToPiid.get(portId, PLAYER_PIID_INVALID);
+ if (piid == PLAYER_PIID_INVALID) {
+ Log.w(TAG, "No piid assigned for invalid/internal port id " + portId);
+ return;
+ }
+ }
+ final AudioPlaybackConfiguration apc = mPlayers.get(piid);
+ if (apc == null) {
+ Log.w(TAG, "No AudioPlaybackConfiguration assigned for piid " + piid);
+ return;
+ }
+
+ if (apc.getPlayerType()
+ == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
+ // FIXME SoundPool not ready for state reporting
+ return;
+ }
+ mEventHandler.sendMessage(
+ mEventHandler.obtainMessage(MSG_IIL_UPDATE_PLAYER_MUTED_EVENT, piid, event, null));
+ }
+ }
+ /**
+ * Update event for port
+ * @param portId Port id to update
* @param event The new port event
* @param extras The values associated with this event
* @param binderUid Calling binder uid
@@ -479,15 +522,10 @@ public final class PlaybackActivityMonitor
return;
}
- if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_MUTED) {
- mEventHandler.sendMessage(
- mEventHandler.obtainMessage(MSG_IIL_UPDATE_PLAYER_MUTED_EVENT, piid,
- portId,
- extras));
- } else if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_FORMAT) {
+ if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_FORMAT) {
mEventHandler.sendMessage(
mEventHandler.obtainMessage(MSG_IIL_UPDATE_PLAYER_FORMAT, piid,
- portId,
+ -1,
extras));
}
}
@@ -1695,9 +1733,7 @@ public final class PlaybackActivityMonitor
* event for player getting muted
* args:
* msg.arg1: piid
- * msg.arg2: port id
- * msg.obj: extras describing the mute reason
- * type: PersistableBundle
+ * msg.arg2: mute reason
*/
private static final int MSG_IIL_UPDATE_PLAYER_MUTED_EVENT = 2;
@@ -1705,7 +1741,6 @@ public final class PlaybackActivityMonitor
* event for player reporting playback format and spatialization status
* args:
* msg.arg1: piid
- * msg.arg2: port id
* msg.obj: extras describing the sample rate, channel mask, spatialized
* type: PersistableBundle
*/
@@ -1729,17 +1764,9 @@ public final class PlaybackActivityMonitor
break;
case MSG_IIL_UPDATE_PLAYER_MUTED_EVENT:
- // TODO: replace PersistableBundle with own struct
- PersistableBundle extras = (PersistableBundle) msg.obj;
- if (extras == null) {
- Log.w(TAG, "Received mute event with no extras");
- break;
- }
- @PlayerMuteEvent int eventValue = extras.getInt(EXTRA_PLAYER_EVENT_MUTE);
-
synchronized (mPlayerLock) {
int piid = msg.arg1;
-
+ @PlayerMuteEvent int eventValue = msg.arg2;
int[] eventValues = new int[1];
eventValues[0] = eventValue;
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 d435144b28c6..b9ce8c93dbde 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -21,6 +21,7 @@ import android.os.Build;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Slog;
+import android.window.DesktopExperienceFlags;
import com.android.server.display.feature.flags.Flags;
import com.android.server.display.utils.DebugUtils;
@@ -250,7 +251,7 @@ public class DisplayManagerFlags {
);
private final FlagState mEnableDisplayContentModeManagementFlagState = new FlagState(
Flags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT,
- Flags::enableDisplayContentModeManagement
+ DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT::isTrue
);
private final FlagState mSubscribeGranularDisplayEvents = new FlagState(
diff --git a/services/core/java/com/android/server/input/InputGestureManager.java b/services/core/java/com/android/server/input/InputGestureManager.java
index fd755e3cefe2..be8a94149fdc 100644
--- a/services/core/java/com/android/server/input/InputGestureManager.java
+++ b/services/core/java/com/android/server/input/InputGestureManager.java
@@ -186,21 +186,11 @@ final class InputGestureManager {
KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT
),
createKeyGesture(
- KeyEvent.KEYCODE_DPAD_LEFT,
- KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT
- ),
- createKeyGesture(
KeyEvent.KEYCODE_DPAD_RIGHT,
KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON,
KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT
),
createKeyGesture(
- KeyEvent.KEYCODE_DPAD_RIGHT,
- KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT
- ),
- createKeyGesture(
KeyEvent.KEYCODE_SLASH,
KeyEvent.META_META_ON,
KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER
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 2a5b779546d5..5259bcc78311 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -29,6 +29,8 @@ import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.hardware.tv.mediaquality.AmbientBacklightColorFormat;
+import android.hardware.tv.mediaquality.DolbyAudioProcessing;
+import android.hardware.tv.mediaquality.DtsVirtualX;
import android.hardware.tv.mediaquality.IMediaQuality;
import android.hardware.tv.mediaquality.PictureParameter;
import android.hardware.tv.mediaquality.PictureParameters;
@@ -461,7 +463,7 @@ public class MediaQualityService extends SystemService {
}
if (params.containsKey(PictureQuality.PARAMETER_AUTO_SUPER_RESOLUTION_ENABLED)) {
pictureParams.add(PictureParameter.autoSuperResolutionEnabled(params.getBoolean(
- PictureQuality.PARAMETER_AUTO_SUPER_RESOLUTION_ENABLED)));
+ PictureQuality.PARAMETER_AUTO_SUPER_RESOLUTION_ENABLED)));
}
if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_RED_GAIN)) {
pictureParams.add(PictureParameter.colorTemperatureRedGain(params.getInt(
@@ -475,63 +477,214 @@ public class MediaQualityService extends SystemService {
pictureParams.add(PictureParameter.colorTemperatureBlueGain(params.getInt(
PictureQuality.PARAMETER_COLOR_TUNER_BLUE_GAIN)));
}
-
- /**
- * TODO: add conversion for following after adding to MediaQualityContract
- *
- * PictureParameter.levelRange
- * PictureParameter.gamutMapping
- * PictureParameter.pcMode
- * PictureParameter.lowLatency
- * PictureParameter.vrr
- * PictureParameter.cvrr
- * PictureParameter.hdmiRgbRange
- * PictureParameter.colorSpace
- * PictureParameter.panelInitMaxLuminceNits
- * PictureParameter.panelInitMaxLuminceValid
- * PictureParameter.gamma
- * PictureParameter.colorTemperatureRedOffset
- * PictureParameter.colorTemperatureGreenOffset
- * PictureParameter.colorTemperatureBlueOffset
- * PictureParameter.elevenPointRed
- * PictureParameter.elevenPointGreen
- * PictureParameter.elevenPointBlue
- * PictureParameter.lowBlueLight
- * PictureParameter.LdMode
- * PictureParameter.osdRedGain
- * PictureParameter.osdGreenGain
- * PictureParameter.osdBlueGain
- * PictureParameter.osdRedOffset
- * PictureParameter.osdGreenOffset
- * PictureParameter.osdBlueOffset
- * PictureParameter.osdHue
- * PictureParameter.osdSaturation
- * PictureParameter.osdContrast
- * PictureParameter.colorTunerSwitch
- * PictureParameter.colorTunerHueRed
- * PictureParameter.colorTunerHueGreen
- * PictureParameter.colorTunerHueBlue
- * PictureParameter.colorTunerHueCyan
- * PictureParameter.colorTunerHueMagenta
- * PictureParameter.colorTunerHueYellow
- * PictureParameter.colorTunerHueFlesh
- * PictureParameter.colorTunerSaturationRed
- * PictureParameter.colorTunerSaturationGreen
- * PictureParameter.colorTunerSaturationBlue
- * PictureParameter.colorTunerSaturationCyan
- * PictureParameter.colorTunerSaturationMagenta
- * PictureParameter.colorTunerSaturationYellow
- * PictureParameter.colorTunerSaturationFlesh
- * PictureParameter.colorTunerLuminanceRed
- * PictureParameter.colorTunerLuminanceGreen
- * PictureParameter.colorTunerLuminanceBlue
- * PictureParameter.colorTunerLuminanceCyan
- * PictureParameter.colorTunerLuminanceMagenta
- * PictureParameter.colorTunerLuminanceYellow
- * PictureParameter.colorTunerLuminanceFlesh
- * PictureParameter.activeProfile
- * PictureParameter.pictureQualityEventType
- */
+ if (params.containsKey(PictureQuality.PARAMETER_LEVEL_RANGE)) {
+ pictureParams.add(PictureParameter.levelRange(
+ (byte) params.getInt(PictureQuality.PARAMETER_LEVEL_RANGE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_GAMUT_MAPPING)) {
+ pictureParams.add(PictureParameter.gamutMapping(params.getBoolean(
+ PictureQuality.PARAMETER_GAMUT_MAPPING)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_PC_MODE)) {
+ pictureParams.add(PictureParameter.pcMode(params.getBoolean(
+ PictureQuality.PARAMETER_PC_MODE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_LOW_LATENCY)) {
+ pictureParams.add(PictureParameter.lowLatency(params.getBoolean(
+ PictureQuality.PARAMETER_LOW_LATENCY)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_VRR)) {
+ pictureParams.add(PictureParameter.vrr(params.getBoolean(
+ PictureQuality.PARAMETER_VRR)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_CVRR)) {
+ pictureParams.add(PictureParameter.cvrr(params.getBoolean(
+ PictureQuality.PARAMETER_CVRR)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_HDMI_RGB_RANGE)) {
+ pictureParams.add(PictureParameter.hdmiRgbRange(
+ (byte) params.getInt(PictureQuality.PARAMETER_HDMI_RGB_RANGE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_SPACE)) {
+ pictureParams.add(PictureParameter.colorSpace(
+ (byte) params.getInt(PictureQuality.PARAMETER_COLOR_SPACE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_PANEL_INIT_MAX_LUMINCE_NITS)) {
+ pictureParams.add(PictureParameter.panelInitMaxLuminceNits(
+ params.getInt(PictureQuality.PARAMETER_PANEL_INIT_MAX_LUMINCE_NITS)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_PANEL_INIT_MAX_LUMINCE_VALID)) {
+ pictureParams.add(PictureParameter.panelInitMaxLuminceValid(
+ params.getBoolean(PictureQuality.PARAMETER_PANEL_INIT_MAX_LUMINCE_VALID)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_GAMMA)) {
+ pictureParams.add(PictureParameter.gamma(
+ (byte) params.getInt(PictureQuality.PARAMETER_GAMMA)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TEMPERATURE_RED_OFFSET)) {
+ pictureParams.add(PictureParameter.colorTemperatureRedOffset(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TEMPERATURE_RED_OFFSET)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TEMPERATURE_GREEN_OFFSET)) {
+ pictureParams.add(PictureParameter.colorTemperatureGreenOffset(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TEMPERATURE_GREEN_OFFSET)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TEMPERATURE_BLUE_OFFSET)) {
+ pictureParams.add(PictureParameter.colorTemperatureBlueOffset(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TEMPERATURE_BLUE_OFFSET)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_ELEVEN_POINT_RED)) {
+ pictureParams.add(PictureParameter.elevenPointRed(params.getIntArray(
+ PictureQuality.PARAMETER_ELEVEN_POINT_RED)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_ELEVEN_POINT_GREEN)) {
+ pictureParams.add(PictureParameter.elevenPointGreen(params.getIntArray(
+ PictureQuality.PARAMETER_ELEVEN_POINT_GREEN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_ELEVEN_POINT_BLUE)) {
+ pictureParams.add(PictureParameter.elevenPointBlue(params.getIntArray(
+ PictureQuality.PARAMETER_ELEVEN_POINT_BLUE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_LOW_BLUE_LIGHT)) {
+ pictureParams.add(PictureParameter.lowBlueLight(
+ (byte) params.getInt(PictureQuality.PARAMETER_LOW_BLUE_LIGHT)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_LD_MODE)) {
+ pictureParams.add(PictureParameter.LdMode(
+ (byte) params.getInt(PictureQuality.PARAMETER_LD_MODE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_RED_GAIN)) {
+ pictureParams.add(PictureParameter.osdRedGain(params.getInt(
+ PictureQuality.PARAMETER_OSD_RED_GAIN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_GREEN_GAIN)) {
+ pictureParams.add(PictureParameter.osdGreenGain(params.getInt(
+ PictureQuality.PARAMETER_OSD_GREEN_GAIN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_BLUE_GAIN)) {
+ pictureParams.add(PictureParameter.osdBlueGain(params.getInt(
+ PictureQuality.PARAMETER_OSD_BLUE_GAIN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_RED_OFFSET)) {
+ pictureParams.add(PictureParameter.osdRedOffset(params.getInt(
+ PictureQuality.PARAMETER_OSD_RED_OFFSET)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_GREEN_OFFSET)) {
+ pictureParams.add(PictureParameter.osdGreenOffset(params.getInt(
+ PictureQuality.PARAMETER_OSD_GREEN_OFFSET)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_BLUE_OFFSET)) {
+ pictureParams.add(PictureParameter.osdBlueOffset(params.getInt(
+ PictureQuality.PARAMETER_OSD_BLUE_OFFSET)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_HUE)) {
+ pictureParams.add(PictureParameter.osdHue(params.getInt(
+ PictureQuality.PARAMETER_OSD_HUE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_SATURATION)) {
+ pictureParams.add(PictureParameter.osdSaturation(params.getInt(
+ PictureQuality.PARAMETER_OSD_SATURATION)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_OSD_CONTRAST)) {
+ pictureParams.add(PictureParameter.osdContrast(params.getInt(
+ PictureQuality.PARAMETER_OSD_CONTRAST)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SWITCH)) {
+ pictureParams.add(PictureParameter.colorTunerSwitch(params.getBoolean(
+ PictureQuality.PARAMETER_COLOR_TUNER_SWITCH)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_HUE_RED)) {
+ pictureParams.add(PictureParameter.colorTunerHueRed(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_HUE_RED)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_HUE_GREEN)) {
+ pictureParams.add(PictureParameter.colorTunerHueGreen(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_HUE_GREEN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_HUE_BLUE)) {
+ pictureParams.add(PictureParameter.colorTunerHueBlue(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_HUE_BLUE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_HUE_CYAN)) {
+ pictureParams.add(PictureParameter.colorTunerHueCyan(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_HUE_CYAN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_HUE_MAGENTA)) {
+ pictureParams.add(PictureParameter.colorTunerHueMagenta(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_HUE_MAGENTA)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_HUE_YELLOW)) {
+ pictureParams.add(PictureParameter.colorTunerHueYellow(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_HUE_YELLOW)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_HUE_FLESH)) {
+ pictureParams.add(PictureParameter.colorTunerHueFlesh(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_HUE_FLESH)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_RED)) {
+ pictureParams.add(PictureParameter.colorTunerSaturationRed(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_RED)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_GREEN)) {
+ pictureParams.add(PictureParameter.colorTunerSaturationGreen(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_GREEN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_BLUE)) {
+ pictureParams.add(PictureParameter.colorTunerSaturationBlue(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_BLUE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_CYAN)) {
+ pictureParams.add(PictureParameter.colorTunerSaturationCyan(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_CYAN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_MAGENTA)) {
+ pictureParams.add(PictureParameter.colorTunerSaturationMagenta(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_MAGENTA)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_YELLOW)) {
+ pictureParams.add(PictureParameter.colorTunerSaturationYellow(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_YELLOW)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_FLESH)) {
+ pictureParams.add(PictureParameter.colorTunerSaturationFlesh(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_SATURATION_FLESH)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_RED)) {
+ pictureParams.add(PictureParameter.colorTunerLuminanceRed(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_RED)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_GREEN)) {
+ pictureParams.add(PictureParameter.colorTunerLuminanceGreen(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_GREEN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_BLUE)) {
+ pictureParams.add(PictureParameter.colorTunerLuminanceBlue(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_BLUE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_CYAN)) {
+ pictureParams.add(PictureParameter.colorTunerLuminanceCyan(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_CYAN)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_MAGENTA)) {
+ pictureParams.add(PictureParameter.colorTunerLuminanceMagenta(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_MAGENTA)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_YELLOW)) {
+ pictureParams.add(PictureParameter.colorTunerLuminanceYellow(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_YELLOW)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_FLESH)) {
+ pictureParams.add(PictureParameter.colorTunerLuminanceFlesh(params.getInt(
+ PictureQuality.PARAMETER_COLOR_TUNER_LUMINANCE_FLESH)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_ACTIVE_PROFILE)) {
+ pictureParams.add(PictureParameter.activeProfile(params.getBoolean(
+ PictureQuality.PARAMETER_ACTIVE_PROFILE)));
+ }
+ if (params.containsKey(PictureQuality.PARAMETER_PICTURE_QUALITY_EVENT_TYPE)) {
+ pictureParams.add(PictureParameter.pictureQualityEventType(
+ (byte) params.getInt(PictureQuality.PARAMETER_PICTURE_QUALITY_EVENT_TYPE)));
+ }
return (PictureParameter[]) pictureParams.toArray();
}
@@ -775,6 +928,7 @@ public class MediaQualityService extends SystemService {
private SoundParameter[] convertPersistableBundleToSoundParameterList(
PersistableBundle params) {
+ //TODO: set EqualizerDetail
List<SoundParameter> soundParams = new ArrayList<>();
if (params.containsKey(SoundQuality.PARAMETER_BALANCE)) {
soundParams.add(SoundParameter.balance(params.getInt(
@@ -811,15 +965,54 @@ public class MediaQualityService extends SystemService {
soundParams.add(SoundParameter.surroundSoundEnabled(params.getBoolean(
SoundQuality.PARAMETER_DIGITAL_OUTPUT_DELAY_MILLIS)));
}
- //TODO: equalizerDetail
- //TODO: downmixMode
- //TODO: enhancedAudioReturnChannelEnabled
- //TODO: dolbyAudioProcessing
- //TODO: dolbyDialogueEnhancer
- //TODO: dtsVirtualX
- //TODO: digitalOutput
- //TODO: activeProfile
- //TODO: soundStyle
+ if (params.containsKey(SoundQuality.PARAMETER_EARC)) {
+ soundParams.add(SoundParameter.enhancedAudioReturnChannelEnabled(params.getBoolean(
+ SoundQuality.PARAMETER_EARC)));
+ }
+ if (params.containsKey(SoundQuality.PARAMETER_DOWN_MIX_MODE)) {
+ soundParams.add(SoundParameter.downmixMode((byte) params.getInt(
+ SoundQuality.PARAMETER_DOWN_MIX_MODE)));
+ }
+ if (params.containsKey(SoundQuality.PARAMETER_ACTIVE_PROFILE)) {
+ soundParams.add(SoundParameter.activeProfile(params.getBoolean(
+ SoundQuality.PARAMETER_ACTIVE_PROFILE)));
+ }
+ if (params.containsKey(SoundQuality.PARAMETER_SOUND_STYLE)) {
+ soundParams.add(SoundParameter.soundStyle((byte) params.getInt(
+ SoundQuality.PARAMETER_SOUND_STYLE)));
+ }
+ if (params.containsKey(SoundQuality.PARAMETER_DIGITAL_OUTPUT_MODE)) {
+ soundParams.add(SoundParameter.digitalOutput((byte) params.getInt(
+ SoundQuality.PARAMETER_DIGITAL_OUTPUT_MODE)));
+ }
+ if (params.containsKey(SoundQuality.PARAMETER_DIALOGUE_ENHANCER)) {
+ soundParams.add(SoundParameter.dolbyDialogueEnhancer((byte) params.getInt(
+ SoundQuality.PARAMETER_DIALOGUE_ENHANCER)));
+ }
+
+ DolbyAudioProcessing dab = new DolbyAudioProcessing();
+ dab.soundMode =
+ (byte) params.getInt(SoundQuality.PARAMETER_DOLBY_AUDIO_PROCESSING_SOUND_MODE);
+ dab.volumeLeveler =
+ params.getBoolean(SoundQuality.PARAMETER_DOLBY_AUDIO_PROCESSING_VOLUME_LEVELER);
+ dab.surroundVirtualizer = params.getBoolean(
+ SoundQuality.PARAMETER_DOLBY_AUDIO_PROCESSING_SURROUND_VIRTUALIZER);
+ dab.dolbyAtmos =
+ params.getBoolean(SoundQuality.PARAMETER_DOLBY_AUDIO_PROCESSING_DOLBY_ATMOS);
+ soundParams.add(SoundParameter.dolbyAudioProcessing(dab));
+
+ DtsVirtualX dts = new DtsVirtualX();
+ dts.tbHdx = params.getBoolean(SoundQuality.PARAMETER_DTS_VIRTUAL_X_TBHDX);
+ dts.limiter = params.getBoolean(SoundQuality.PARAMETER_DTS_VIRTUAL_X_LIMITER);
+ dts.truSurroundX = params.getBoolean(
+ SoundQuality.PARAMETER_DTS_VIRTUAL_X_TRU_SURROUND_X);
+ dts.truVolumeHd = params.getBoolean(SoundQuality.PARAMETER_DTS_VIRTUAL_X_TRU_VOLUME_HD);
+ dts.dialogClarity = params.getBoolean(
+ SoundQuality.PARAMETER_DTS_VIRTUAL_X_DIALOG_CLARITY);
+ dts.definition = params.getBoolean(SoundQuality.PARAMETER_DTS_VIRTUAL_X_DEFINITION);
+ dts.height = params.getBoolean(SoundQuality.PARAMETER_DTS_VIRTUAL_X_HEIGHT);
+ soundParams.add(SoundParameter.dtsVirtualX(dts));
+
return (SoundParameter[]) soundParams.toArray();
}
@@ -1472,7 +1665,13 @@ public class MediaQualityService extends SystemService {
RemoteCallbackList<IPictureProfileCallback> {
@Override
public void onCallbackDied(IPictureProfileCallback callback) {
- //todo
+ synchronized ("mPictureProfileLock") { //TODO: Change to lock
+ for (int i = 0; i < mUserStates.size(); i++) {
+ int userId = mUserStates.keyAt(i);
+ UserState userState = getOrCreateUserStateLocked(userId);
+ userState.mPictureProfileCallbackPidUidMap.remove(callback);
+ }
+ }
}
}
@@ -1480,7 +1679,13 @@ public class MediaQualityService extends SystemService {
RemoteCallbackList<ISoundProfileCallback> {
@Override
public void onCallbackDied(ISoundProfileCallback callback) {
- //todo
+ synchronized ("mSoundProfileLock") { //TODO: Change to lock
+ for (int i = 0; i < mUserStates.size(); i++) {
+ int userId = mUserStates.keyAt(i);
+ UserState userState = getOrCreateUserStateLocked(userId);
+ userState.mSoundProfileCallbackPidUidMap.remove(callback);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1b1c99cf1410..0d3c18ac339f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -481,7 +481,8 @@ public class NotificationManagerService extends SystemService {
Adjustment.KEY_SENSITIVE_CONTENT,
Adjustment.KEY_RANKING_SCORE,
Adjustment.KEY_NOT_CONVERSATION,
- Adjustment.KEY_TYPE
+ Adjustment.KEY_TYPE,
+ Adjustment.KEY_SUMMARIZATION
};
static final Integer[] DEFAULT_ALLOWED_ADJUSTMENT_KEY_TYPES = new Integer[] {
@@ -10432,7 +10433,8 @@ public class NotificationManagerService extends SystemService {
r.getRankingScore(),
r.isConversation(),
r.getProposedImportance(),
- r.hasSensitiveContent());
+ r.hasSensitiveContent(),
+ r.getSummarization());
extractorDataBefore.put(r.getKey(), extractorData);
mRankingHelper.extractSignals(r);
}
@@ -11752,7 +11754,8 @@ public class NotificationManagerService extends SystemService {
: (record.getRankingScore() > 0 ? RANKING_PROMOTED : RANKING_DEMOTED),
record.getNotification().isBubbleNotification(),
record.getProposedImportance(),
- hasSensitiveContent
+ hasSensitiveContent,
+ record.getSummarization()
);
rankings.add(ranking);
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 81af0d8a6d80..52101e336920 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -25,6 +25,7 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.service.notification.Adjustment.KEY_SUMMARIZATION;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
@@ -225,6 +226,8 @@ public final class NotificationRecord {
// type of the bundle if the notification was classified
private @Adjustment.Types int mBundleType = Adjustment.TYPE_OTHER;
+ private String mSummarization = null;
+
public NotificationRecord(Context context, StatusBarNotification sbn,
NotificationChannel channel) {
this.sbn = sbn;
@@ -589,6 +592,7 @@ public final class NotificationRecord {
pw.println(prefix + "shortcut=" + notification.getShortcutId()
+ " found valid? " + (mShortcutInfo != null));
pw.println(prefix + "mUserVisOverride=" + getPackageVisibilityOverride());
+ pw.println(prefix + "hasSummarization=" + (mSummarization != null));
}
private void dumpNotification(PrintWriter pw, String prefix, Notification notification,
@@ -811,6 +815,12 @@ public final class NotificationRecord {
Adjustment.KEY_TYPE,
mChannel.getId());
}
+ if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization())
+ && signals.containsKey(KEY_SUMMARIZATION)) {
+ mSummarization = signals.getString(KEY_SUMMARIZATION);
+ EventLogTags.writeNotificationAdjusted(getKey(),
+ KEY_SUMMARIZATION, Boolean.toString(mSummarization != null));
+ }
if (!signals.isEmpty() && adjustment.getIssuer() != null) {
mAdjustmentIssuer = adjustment.getIssuer();
}
@@ -983,6 +993,13 @@ public final class NotificationRecord {
return null;
}
+ public String getSummarization() {
+ if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization())) {
+ return mSummarization;
+ }
+ return null;
+ }
+
public boolean setIntercepted(boolean intercept) {
mIntercept = intercept;
mInterceptSet = true;
diff --git a/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java b/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java
index 3f4f7d3bbc38..9315ddc0d5b0 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java
@@ -47,6 +47,7 @@ public final class NotificationRecordExtractorData {
private final boolean mIsConversation;
private final int mProposedImportance;
private final boolean mSensitiveContent;
+ private final String mSummarization;
NotificationRecordExtractorData(int position, int visibility, boolean showBadge,
boolean allowBubble, boolean isBubble, NotificationChannel channel, String groupKey,
@@ -54,7 +55,8 @@ public final class NotificationRecordExtractorData {
Integer userSentiment, Integer suppressVisually,
ArrayList<Notification.Action> systemSmartActions,
ArrayList<CharSequence> smartReplies, int importance, float rankingScore,
- boolean isConversation, int proposedImportance, boolean sensitiveContent) {
+ boolean isConversation, int proposedImportance, boolean sensitiveContent,
+ String summarization) {
mPosition = position;
mVisibility = visibility;
mShowBadge = showBadge;
@@ -73,6 +75,7 @@ public final class NotificationRecordExtractorData {
mIsConversation = isConversation;
mProposedImportance = proposedImportance;
mSensitiveContent = sensitiveContent;
+ mSummarization = summarization;
}
// Returns whether the provided NotificationRecord differs from the cached data in any way.
@@ -93,7 +96,8 @@ public final class NotificationRecordExtractorData {
|| !Objects.equals(mSmartReplies, r.getSmartReplies())
|| mImportance != r.getImportance()
|| mProposedImportance != r.getProposedImportance()
- || mSensitiveContent != r.hasSensitiveContent();
+ || mSensitiveContent != r.hasSensitiveContent()
+ || !Objects.equals(mSummarization, r.getSummarization());
}
// Returns whether the NotificationRecord has a change from this data for which we should
@@ -117,6 +121,7 @@ public final class NotificationRecordExtractorData {
|| !r.rankingScoreMatches(mRankingScore)
|| mIsConversation != r.isConversation()
|| mProposedImportance != r.getProposedImportance()
- || mSensitiveContent != r.hasSensitiveContent();
+ || mSensitiveContent != r.hasSensitiveContent()
+ || !Objects.equals(mSummarization, r.getSummarization());
}
}
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 0b58c759b284..f011d283c8bb 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -96,6 +96,9 @@ import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
@@ -105,6 +108,11 @@ import java.util.function.Predicate;
public final class DexOptHelper {
private static final long SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;
+ @NonNull
+ private static final ThreadPoolExecutor sDexoptExecutor =
+ new ThreadPoolExecutor(1 /* corePoolSize */, 1 /* maximumPoolSize */,
+ 60 /* keepAliveTime */, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
+
private static boolean sArtManagerLocalIsInitialized = false;
private final PackageManagerService mPm;
@@ -113,6 +121,11 @@ public final class DexOptHelper {
// used, to make it available to the onDexoptDone callback.
private volatile long mBootDexoptStartTime;
+ static {
+ // Recycle the thread if it's not used for `keepAliveTime`.
+ sDexoptExecutor.allowsCoreThreadTimeOut();
+ }
+
DexOptHelper(PackageManagerService pm) {
mPm = pm;
}
@@ -746,43 +759,11 @@ public final class DexOptHelper {
*/
static void performDexoptIfNeeded(InstallRequest installRequest, DexManager dexManager,
Context context, PackageManagerTracedLock.RawLock installLock) {
-
// Construct the DexoptOptions early to see if we should skip running dexopt.
- //
- // Do not run PackageDexOptimizer through the local performDexOpt
- // method because `pkg` may not be in `mPackages` yet.
- //
- // Also, don't fail application installs if the dexopt step fails.
DexoptOptions dexoptOptions = getDexoptOptionsByInstallRequest(installRequest, dexManager);
- // Check whether we need to dexopt the app.
- //
- // NOTE: it is IMPORTANT to call dexopt:
- // - after doRename which will sync the package data from AndroidPackage and
- // its corresponding ApplicationInfo.
- // - after installNewPackageLIF or replacePackageLIF which will update result with the
- // uid of the application (pkg.applicationInfo.uid).
- // This update happens in place!
- //
- // We only need to dexopt if the package meets ALL of the following conditions:
- // 1) it is not an instant app or if it is then dexopt is enabled via gservices.
- // 2) it is not debuggable.
- // 3) it is not on Incremental File System.
- //
- // Note that we do not dexopt instant apps by default. dexopt can take some time to
- // complete, so we skip this step during installation. Instead, we'll take extra time
- // the first time the instant app starts. It's preferred to do it this way to provide
- // continuous progress to the useur instead of mysteriously blocking somewhere in the
- // middle of running an instant app. The default behaviour can be overridden
- // via gservices.
- //
- // Furthermore, dexopt may be skipped, depending on the install scenario and current
- // state of the device.
- //
- // TODO(b/174695087): instantApp and onIncremental should be removed and their install
- // path moved to SCENARIO_FAST.
+ boolean performDexopt =
+ DexOptHelper.shouldPerformDexopt(installRequest, dexoptOptions, context);
- final boolean performDexopt = DexOptHelper.shouldPerformDexopt(installRequest,
- dexoptOptions, context);
if (performDexopt) {
// dexopt can take long, and ArtService doesn't require installd, so we release
// the lock here and re-acquire the lock after dexopt is finished.
@@ -791,6 +772,7 @@ public final class DexOptHelper {
}
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+ // Don't fail application installs if the dexopt step fails.
DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService(
installRequest, dexoptOptions);
installRequest.onDexoptFinished(dexOptResult);
@@ -804,6 +786,41 @@ public final class DexOptHelper {
}
/**
+ * Same as above, but runs asynchronously.
+ */
+ static CompletableFuture<Void> performDexoptIfNeededAsync(InstallRequest installRequest,
+ DexManager dexManager, Context context) {
+ // Construct the DexoptOptions early to see if we should skip running dexopt.
+ DexoptOptions dexoptOptions = getDexoptOptionsByInstallRequest(installRequest, dexManager);
+ boolean performDexopt =
+ DexOptHelper.shouldPerformDexopt(installRequest, dexoptOptions, context);
+
+ if (performDexopt) {
+ return CompletableFuture
+ .runAsync(() -> {
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+ // Don't fail application installs if the dexopt step fails.
+ // TODO(jiakaiz): Make this async in ART Service.
+ DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService(
+ installRequest, dexoptOptions);
+ installRequest.onDexoptFinished(dexOptResult);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }, sDexoptExecutor)
+ .exceptionally((t) -> {
+ // This should never happen. A normal dexopt failure should result in a
+ // DexoptResult.DEXOPT_FAILED, not an exception.
+ Slog.wtf(TAG, "Dexopt encountered a fatal error", t);
+ return null;
+ });
+ } else {
+ return CompletableFuture.completedFuture(null);
+ }
+ }
+
+ /**
* Use ArtService to perform dexopt by the given InstallRequest.
*/
static DexoptResult dexoptPackageUsingArtService(InstallRequest installRequest,
@@ -840,6 +857,20 @@ public final class DexOptHelper {
*/
static boolean shouldPerformDexopt(InstallRequest installRequest, DexoptOptions dexoptOptions,
Context context) {
+ // We only need to dexopt if the package meets ALL of the following conditions:
+ // 1) it is not an instant app or if it is then dexopt is enabled via gservices.
+ // 2) it is not debuggable.
+ // 3) it is not on Incremental File System.
+ //
+ // Note that we do not dexopt instant apps by default. dexopt can take some time to
+ // complete, so we skip this step during installation. Instead, we'll take extra time
+ // the first time the instant app starts. It's preferred to do it this way to provide
+ // continuous progress to the user instead of mysteriously blocking somewhere in the
+ // middle of running an instant app. The default behaviour can be overridden
+ // via gservices.
+ //
+ // Furthermore, dexopt may be skipped, depending on the install scenario and current
+ // state of the device.
final boolean isApex = ((installRequest.getScanFlags() & SCAN_AS_APEX) != 0);
final boolean instantApp = ((installRequest.getScanFlags() & SCAN_AS_INSTANT_APP) != 0);
final PackageSetting ps = installRequest.getScannedPackageSetting();
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 8eb5b6f11cb2..0c2782393879 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -1158,6 +1158,7 @@ final class InstallPackageHelper {
return;
}
request.setKeepArtProfile(true);
+ // TODO(b/388159696): Use performDexoptIfNeededAsync.
DexOptHelper.performDexoptIfNeeded(request, mDexManager, mContext, null);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 14b0fc81fdd2..c62aaebf673b 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -584,6 +584,12 @@ public abstract class UserManagerInternal {
* Returns the user id of the main user, or {@link android.os.UserHandle#USER_NULL} if there is
* no main user.
*
+ * <p>NB: Features should ideally not limit functionality to the main user. Ideally, they
+ * should either work for all users or for all admin users. If a feature should only work for
+ * select users, its determination of which user should be done intelligently or be
+ * customizable. Not all devices support a main user, and the idea of singling out one user as
+ * special is contrary to overall multiuser goals.
+ *
* @see UserManager#isMainUser()
*/
public abstract @UserIdInt int getMainUserId();
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a2c53e56b9c9..8cbccf5feead 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3590,8 +3590,6 @@ public class UserManagerService extends IUserManager.Stub {
}
/**
- * @hide
- *
* Returns who set a user restriction on a user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param restrictionKey the string key representing the restriction
@@ -6275,9 +6273,6 @@ public class UserManagerService extends IUserManager.Stub {
}
}
- /**
- * @hide
- */
@Override
public @NonNull UserInfo createRestrictedProfileWithThrow(
@Nullable String name, @UserIdInt int parentUserId)
@@ -8504,7 +8499,6 @@ public class UserManagerService extends IUserManager.Stub {
}
/**
- * @hide
* Checks whether to show a notification for sounds (e.g., alarms, timers, etc.) from
* background users.
*/
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7f511e1e2aa1..283979483e73 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3801,10 +3801,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
true /* leftOrTop */);
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT);
- } else if (event.isAltPressed()) {
- setSplitscreenFocus(true /* leftOrTop */);
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT);
} else {
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_BACK);
@@ -3821,11 +3817,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT);
return true;
- } else if (event.isAltPressed()) {
- setSplitscreenFocus(false /* leftOrTop */);
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT);
- return true;
}
}
break;
@@ -4241,9 +4232,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION:
case KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE:
case KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT:
- case KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT:
case KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT:
- case KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT:
case KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER:
case KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_UP:
case KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_DOWN:
@@ -4379,22 +4368,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
true /* leftOrTop */);
}
return true;
- case KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT:
- if (complete) {
- setSplitscreenFocus(true /* leftOrTop */);
- }
- return true;
case KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT:
if (complete) {
moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyGestureEvent(event),
false /* leftOrTop */);
}
return true;
- case KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT:
- if (complete) {
- setSplitscreenFocus(false /* leftOrTop */);
- }
- return true;
case KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER:
if (complete) {
toggleKeyboardShortcutsMenu(deviceId);
@@ -5084,13 +5063,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private void setSplitscreenFocus(boolean leftOrTop) {
- StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
- if (statusbar != null) {
- statusbar.setSplitscreenFocus(leftOrTop);
- }
- }
-
void launchHomeFromHotKey(int displayId) {
launchHomeFromHotKey(displayId, true /* awakenFromDreams */, true /*respectKeyguard*/);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 4827c9f414ad..0ed522805bef 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -56,12 +56,12 @@ public interface StatusBarManagerInternal {
void toggleKeyboardShortcutsMenu(int deviceId);
/**
- * Used by InputMethodManagerService to notify the IME status.
+ * Sets the new IME window status.
*
- * @param displayId The display to which the IME is bound to.
- * @param vis The IME visibility.
- * @param backDisposition The IME back disposition.
- * @param showImeSwitcher {@code true} when the IME switcher button should be shown.
+ * @param displayId The id of the display to which the IME is bound.
+ * @param vis The IME window visibility.
+ * @param backDisposition The IME back disposition mode.
+ * @param showImeSwitcher Whether the IME Switcher button should be shown.
*/
void setImeWindowStatus(int displayId, @ImeWindowVisibility int vis,
@BackDispositionMode int backDisposition, boolean showImeSwitcher);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 8a3ee61d5d80..83e146df3e53 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -118,6 +118,7 @@ import android.service.wallpaper.WallpaperService;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.EventLog;
import android.util.IntArray;
import android.util.Slog;
@@ -160,6 +161,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -805,12 +807,38 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
final WallpaperDisplayHelper mWallpaperDisplayHelper;
final WallpaperCropper mWallpaperCropper;
- private boolean supportsMultiDisplay(WallpaperConnection connection) {
- if (connection != null) {
- return connection.mInfo == null // This is image wallpaper
- || connection.mInfo.supportsMultipleDisplays();
+ // TODO(b/384519749): Remove this set after we introduce the aspect ratio check.
+ private final Set<Integer> mWallpaperCompatibleDisplaysForTest = new ArraySet<>();
+
+ private boolean isWallpaperCompatibleForDisplay(int displayId, WallpaperConnection connection) {
+ if (connection == null) {
+ return false;
}
- return false;
+ // Non image wallpaper.
+ if (connection.mInfo != null) {
+ return connection.mInfo.supportsMultipleDisplays();
+ }
+
+ // Image wallpaper
+ if (enableConnectedDisplaysWallpaper()) {
+ // TODO(b/384519749): check display's resolution and image wallpaper cropped image
+ // aspect ratio.
+ return displayId == DEFAULT_DISPLAY
+ || mWallpaperCompatibleDisplaysForTest.contains(displayId);
+ }
+ // When enableConnectedDisplaysWallpaper is off, we assume the image wallpaper supports all
+ // usable displays.
+ return true;
+ }
+
+ @VisibleForTesting
+ void addWallpaperCompatibleDisplayForTest(int displayId) {
+ mWallpaperCompatibleDisplaysForTest.add(displayId);
+ }
+
+ @VisibleForTesting
+ void removeWallpaperCompatibleDisplayForTest(int displayId) {
+ mWallpaperCompatibleDisplaysForTest.remove(displayId);
}
private void updateFallbackConnection() {
@@ -821,7 +849,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
Slog.w(TAG, "Fallback wallpaper connection has not been created yet!!");
return;
}
- if (supportsMultiDisplay(systemConnection)) {
+ // TODO(b/384520326) Passing DEFAULT_DISPLAY temporarily before we revamp the
+ // multi-display supports.
+ if (isWallpaperCompatibleForDisplay(DEFAULT_DISPLAY, systemConnection)) {
if (fallbackConnection.mDisplayConnector.size() != 0) {
fallbackConnection.forEachDisplayConnector(connector -> {
if (connector.mEngine != null) {
@@ -996,16 +1026,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
private void initDisplayState() {
// Do not initialize fallback wallpaper
if (!mWallpaper.equals(mFallbackWallpaper)) {
- if (supportsMultiDisplay(this)) {
- // The system wallpaper is image wallpaper or it can supports multiple displays.
- appendConnectorWithCondition(display ->
- mWallpaperDisplayHelper.isUsableDisplay(display, mClientUid));
- } else {
- // The system wallpaper does not support multiple displays, so just attach it on
- // default display.
- mDisplayConnector.append(DEFAULT_DISPLAY,
- new DisplayConnector(DEFAULT_DISPLAY));
- }
+ appendConnectorWithCondition(display -> {
+ final int displayId = display.getDisplayId();
+ if (display.getDisplayId() == DEFAULT_DISPLAY) {
+ return true;
+ }
+ return mWallpaperDisplayHelper.isUsableDisplay(display, mClientUid)
+ && isWallpaperCompatibleForDisplay(displayId, /* connection= */ this);
+ });
}
}
@@ -3990,7 +4018,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
for (int i = 0; i < wallpapers.size(); i++) {
WallpaperData wallpaper = wallpapers.get(i);
- if (supportsMultiDisplay(wallpaper.connection)) {
+ if (isWallpaperCompatibleForDisplay(displayId, wallpaper.connection)) {
final DisplayConnector connector =
wallpaper.connection.getDisplayConnectorOrCreate(displayId);
if (connector != null) {
@@ -4012,7 +4040,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
mFallbackWallpaper.mWhich = useFallbackWallpaperWhich;
} else {
- if (supportsMultiDisplay(mLastWallpaper.connection)) {
+ if (isWallpaperCompatibleForDisplay(displayId, mLastWallpaper.connection)) {
final DisplayConnector connector =
mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
if (connector == null) return;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 1d12c561f118..064ef1aa0eff 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3231,8 +3231,8 @@ final class ActivityRecord extends WindowToken {
* Returns {@code true} if the fixed orientation, aspect ratio, resizability of the application
* can be ignored.
*/
- static boolean canBeUniversalResizeable(ApplicationInfo appInfo, WindowManagerService wms,
- boolean isLargeScreen, boolean forActivity) {
+ static boolean canBeUniversalResizeable(@NonNull ApplicationInfo appInfo,
+ WindowManagerService wms, boolean isLargeScreen, boolean forActivity) {
if (appInfo.category == ApplicationInfo.CATEGORY_GAME) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d4f9c0901162..cf111cdbcc6a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2154,6 +2154,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
+ /**
+ * @return ehether the application could be universal resizeable on a large screen,
+ * ignoring any overrides
+ */
+ @Override
+ public boolean canBeUniversalResizeable(@NonNull ApplicationInfo appInfo) {
+ return ActivityRecord.canBeUniversalResizeable(appInfo, mWindowManager,
+ /* isLargeScreen */ true, /* forActivity */ false);
+ }
+
@Override
public void removeAllVisibleRecentTasks() {
mAmInternal.enforceCallingPermission(REMOVE_TASKS, "removeAllVisibleRecentTasks()");
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 37cc0d22c063..27683b2fcff2 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1504,16 +1504,15 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
// Update the input-sink (touch-blocking) state now that the animation is finished.
- SurfaceControl.Transaction inputSinkTransaction = null;
+ boolean scheduleAnimation = false;
for (int i = 0; i < mParticipants.size(); ++i) {
final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
if (ar == null || !ar.isVisible() || ar.getParent() == null) continue;
- if (inputSinkTransaction == null) {
- inputSinkTransaction = ar.mWmService.mTransactionFactory.get();
- }
- ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(inputSinkTransaction);
+ scheduleAnimation = true;
+ ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(ar.getPendingTransaction());
}
- if (inputSinkTransaction != null) inputSinkTransaction.apply();
+ // To apply pending transactions.
+ if (scheduleAnimation) mController.mAtm.mWindowManager.scheduleAnimationLocked();
// Always schedule stop processing when transition finishes because activities don't
// stop while they are in a transition thus their stop could still be pending.
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 27eada013642..89b48bad2358 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
@@ -16,8 +16,6 @@
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.Process.INVALID_UID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -29,11 +27,9 @@ 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 org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -43,11 +39,9 @@ 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;
@@ -185,34 +179,6 @@ 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);
- pir.clearAllowBgActivityStarts(token);
- PendingIntentRecord.TempAllowListDuration allowlistDurationLockedAfterClear =
- pir.getAllowlistDurationLocked(token);
- assertNull(allowlistDurationLockedAfterClear);
- }
-
private void assertCancelReason(int expectedReason, int actualReason) {
final String errMsg = "Expected: " + cancelReasonToString(expectedReason)
+ "; Actual: " + cancelReasonToString(actualReason);
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index f583d4e67cc2..793ba7bc89bd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -728,7 +728,7 @@ public class WallpaperManagerServiceTests {
final int testDisplayId = 2;
setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
- // WHEN displayId, 2, is ready.
+ // WHEN display ID, 2, is ready.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
wallpaperManagerInternal.onDisplayReady(testDisplayId);
@@ -768,7 +768,7 @@ public class WallpaperManagerServiceTests {
final int testDisplayId = 2;
setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
- // WHEN displayId, 2, is ready.
+ // WHEN display ID, 2, is ready.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
wallpaperManagerInternal.onDisplayReady(testDisplayId);
@@ -800,6 +800,40 @@ public class WallpaperManagerServiceTests {
/* info= */ any(),
/* description= */ any());
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
+ public void displayAdded_wallpaperIncompatibleForDisplay_shouldAttachFallbackWallpaperService()
+ throws Exception {
+ final int testUserId = USER_SYSTEM;
+ mService.switchUser(testUserId, null);
+ IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
+ mService.mFallbackWallpaper.connection.mService = mockIWallpaperService;
+ // GIVEN there are two displays: DEFAULT_DISPLAY, 2
+ final int testDisplayId = 2;
+ setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ // GIVEN the wallpaper isn't compatible with display ID, 2
+ mService.removeWallpaperCompatibleDisplayForTest(testDisplayId);
+
+ // WHEN display ID, 2, is ready.
+ WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
+ WallpaperManagerInternal.class);
+ wallpaperManagerInternal.onDisplayReady(testDisplayId);
+
+ // Then there is a connection established for the fallback wallpaper for display ID, 2.
+ verify(mockIWallpaperService).attach(
+ /* connection= */ eq(mService.mFallbackWallpaper.connection),
+ /* windowToken= */ any(),
+ /* windowType= */ anyInt(),
+ /* isPreview= */ anyBoolean(),
+ /* reqWidth= */ anyInt(),
+ /* reqHeight= */ anyInt(),
+ /* padding= */ any(),
+ /* displayId= */ eq(testDisplayId),
+ /* which= */ eq(FLAG_SYSTEM | FLAG_LOCK),
+ /* info= */ any(),
+ /* description= */ any());
+ }
// Verify a secondary display added end
// Verify a secondary display removed started
@@ -819,7 +853,7 @@ public class WallpaperManagerServiceTests {
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
- // GIVEN wallpaper connections have been established for displayID, 2.
+ // GIVEN wallpaper connections have been established for display ID, 2.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
wallpaperManagerInternal.onDisplayReady(testDisplayId);
@@ -827,11 +861,11 @@ public class WallpaperManagerServiceTests {
WallpaperManagerService.DisplayConnector displayConnector =
wallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);
- // WHEN displayId, 2, is removed.
+ // WHEN display ID, 2, is removed.
DisplayListener displayListener = displayListenerCaptor.getValue();
displayListener.onDisplayRemoved(testDisplayId);
- // Then the wallpaper connection for displayId, 2, is detached.
+ // Then the wallpaper connection for display ID, 2, is detached.
verify(mockIWallpaperService).detach(eq(displayConnector.mToken));
}
@@ -857,25 +891,57 @@ public class WallpaperManagerServiceTests {
// GIVEN there are two displays: DEFAULT_DISPLAY, 2
final int testDisplayId = 2;
setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
- // GIVEN wallpaper connections have been established for displayID, 2.
+ // GIVEN wallpaper connections have been established for display ID, 2.
WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
WallpaperManagerInternal.class);
wallpaperManagerInternal.onDisplayReady(testDisplayId);
- // Save displayConnectors for displayId 2 before display removal.
+ // Save displayConnectors for display ID, 2, before display removal.
WallpaperManagerService.DisplayConnector systemWallpaperDisplayConnector =
systemWallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);
WallpaperManagerService.DisplayConnector lockWallpaperDisplayConnector =
lockWallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);
- // WHEN displayId, 2, is removed.
+ // WHEN display ID, 2, is removed.
DisplayListener displayListener = displayListenerCaptor.getValue();
displayListener.onDisplayRemoved(testDisplayId);
- // Then the system wallpaper connection for displayId, 2, is detached.
+ // Then the system wallpaper connection for display ID, 2, is detached.
verify(mockIWallpaperService).detach(eq(systemWallpaperDisplayConnector.mToken));
- // Then the lock wallpaper connection for displayId, 2, is detached.
+ // Then the lock wallpaper connection for display ID, 2, is detached.
verify(mockIWallpaperService).detach(eq(lockWallpaperDisplayConnector.mToken));
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
+ public void displayRemoved_fallbackWallpaper_shouldDetachFallbackWallpaperService()
+ throws Exception {
+ ArgumentCaptor<DisplayListener> displayListenerCaptor = ArgumentCaptor.forClass(
+ DisplayListener.class);
+ verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), eq(null));
+ final int testUserId = USER_SYSTEM;
+ mService.switchUser(testUserId, null);
+ IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
+ mService.mFallbackWallpaper.connection.mService = mockIWallpaperService;
+ // GIVEN there are two displays: DEFAULT_DISPLAY, 2
+ final int testDisplayId = 2;
+ setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
+ // GIVEN display ID, 2, is incompatible with the wallpaper.
+ mService.removeWallpaperCompatibleDisplayForTest(testDisplayId);
+ // GIVEN wallpaper connections have been established for display ID, 2.
+ WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
+ WallpaperManagerInternal.class);
+ wallpaperManagerInternal.onDisplayReady(testDisplayId);
+ // Save fallback wallpaper displayConnector for display ID, 2, before display removal.
+ WallpaperManagerService.DisplayConnector fallbackWallpaperConnector =
+ mService.mFallbackWallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);
+
+ // WHEN displayId, 2, is removed.
+ DisplayListener displayListener = displayListenerCaptor.getValue();
+ displayListener.onDisplayRemoved(testDisplayId);
+
+ // Then the fallback wallpaper connection for display ID, 2, is detached.
+ verify(mockIWallpaperService).detach(eq(fallbackWallpaperConnector.mToken));
+ }
// Verify a secondary display removed ended
// Test fallback wallpaper after enabling connected display supports.
@@ -971,6 +1037,7 @@ public class WallpaperManagerServiceTests {
doReturn(mockDisplay).when(mDisplayManager).getDisplay(eq(displayId));
doReturn(displayId).when(mockDisplay).getDisplayId();
doReturn(true).when(mockDisplay).hasAccess(anyInt());
+ mService.addWallpaperCompatibleDisplayForTest(displayId);
}
doReturn(mockDisplays).when(mDisplayManager).getDisplays();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
index ecc48bfc40e4..f55ca0c0b12b 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
@@ -57,6 +57,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
+import com.android.server.accessibility.autoclick.AutoclickController;
import com.android.server.accessibility.gestures.TouchExplorer;
import com.android.server.accessibility.magnification.FullScreenMagnificationGestureHandler;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 5602fb76e6f5..28e5be505556 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -68,7 +68,6 @@ import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.admin.DevicePolicyManager;
-import android.app.ecm.EnhancedConfirmationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -2120,23 +2119,6 @@ public class AccessibilityManagerServiceTest {
}
@Test
- @EnableFlags({android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED,
- android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS})
- public void isAccessibilityTargetAllowed_nonSystemUserId_useEcmWithNonSystemUserId() {
- String fakePackageName = "FAKE_PACKAGE_NAME";
- int uid = 0; // uid is not used in the actual implementation when flags are on
- int userId = mTestableContext.getUserId() + 1234;
- when(mDevicePolicyManager.getPermittedAccessibilityServices(userId)).thenReturn(
- List.of(fakePackageName));
- Context mockUserContext = mock(Context.class);
- mTestableContext.addMockUserContext(userId, mockUserContext);
-
- mA11yms.isAccessibilityTargetAllowed(fakePackageName, uid, userId);
-
- verify(mockUserContext).getSystemService(EnhancedConfirmationManager.class);
- }
-
- @Test
@EnableFlags(com.android.hardware.input.Flags.FLAG_ENABLE_TALKBACK_AND_MAGNIFIER_KEY_GESTURES)
public void handleKeyGestureEvent_toggleMagnifier() {
mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_ACCESSIBILITY);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AutoclickControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
index acce813ff659..f02bdae1d9e6 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AutoclickControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.accessibility;
+package com.android.server.accessibility.autoclick;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -39,6 +39,8 @@ import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
+import com.android.server.accessibility.AccessibilityTraceManager;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
diff --git a/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java b/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java
index ef9580c54de6..cbe2bfb26cd6 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java
@@ -28,8 +28,10 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.Manifest;
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
@@ -38,6 +40,7 @@ import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.IAudioDeviceVolumeDispatcher;
import android.media.VolumeInfo;
+import android.os.IpcDataCache;
import android.os.PermissionEnforcer;
import android.os.RemoteException;
import android.os.test.TestLooper;
@@ -83,6 +86,7 @@ public class AbsoluteVolumeBehaviorTest {
@Before
public void setUp() throws Exception {
+ IpcDataCache.disableForTestMode();
mTestLooper = new TestLooper();
mContext = spy(ApplicationProvider.getApplicationContext());
@@ -93,6 +97,10 @@ public class AbsoluteVolumeBehaviorTest {
when(mResources.getBoolean(com.android.internal.R.bool.config_useFixedVolume))
.thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(
+ Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+
mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
mSystemServer = new NoOpSystemServerAdapter();
mSettingsAdapter = new NoOpSettingsAdapter();
diff --git a/services/tests/servicestests/src/com/android/server/audio/DeviceVolumeBehaviorTest.java b/services/tests/servicestests/src/com/android/server/audio/DeviceVolumeBehaviorTest.java
index 746645a8c585..541dbba67957 100644
--- a/services/tests/servicestests/src/com/android/server/audio/DeviceVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/DeviceVolumeBehaviorTest.java
@@ -28,6 +28,7 @@ import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.IDeviceVolumeBehaviorDispatcher;
+import android.os.IpcDataCache;
import android.os.PermissionEnforcer;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
@@ -69,6 +70,7 @@ public class DeviceVolumeBehaviorTest {
@Before
public void setUp() throws Exception {
+ IpcDataCache.disableForTestMode();
mTestLooper = new TestLooper();
mContext = InstrumentationRegistry.getTargetContext();
mAudioSystem = new NoOpAudioSystemAdapter();
diff --git a/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java
index 6b41c434b80f..0bbae247d8bb 100644
--- a/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java
@@ -80,6 +80,7 @@ import android.media.AudioSystem;
import android.media.IDeviceVolumeBehaviorDispatcher;
import android.media.VolumeInfo;
import android.media.audiopolicy.AudioVolumeGroup;
+import android.os.IpcDataCache;
import android.os.Looper;
import android.os.PermissionEnforcer;
import android.os.test.TestLooper;
@@ -210,6 +211,8 @@ public class VolumeHelperTest {
@Before
public void setUp() throws Exception {
+ IpcDataCache.disableForTestMode();
+
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
mTestLooper = new TestLooper();
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 2f3bca031f46..fbb673a194b4 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -1762,7 +1762,8 @@ public final class DataManagerTest {
/* rankingAdjustment= */ 0,
/* isBubble= */ false,
/* proposedImportance= */ 0,
- /* sensitiveContent= */ false
+ /* sensitiveContent= */ false,
+ /* summarization = */ null
);
return true;
}).when(mRankingMap).getRanking(eq(key),
@@ -1806,7 +1807,8 @@ public final class DataManagerTest {
/* rankingAdjustment= */ 0,
/* isBubble= */ false,
/* proposedImportance= */ 0,
- /* sensitiveContent= */ false
+ /* sensitiveContent= */ false,
+ /* summarization = */ null
);
return true;
}).when(mRankingMap).getRanking(eq(CUSTOM_KEY),
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 8fad01a7541d..2616ccbe474a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -247,7 +247,8 @@ public class NotificationListenerServiceTest extends UiServiceTestCase {
getRankingAdjustment(i),
isBubble(i),
getProposedImportance(i),
- hasSensitiveContent(i)
+ hasSensitiveContent(i),
+ getSummarization(i)
);
rankings[i] = ranking;
}
@@ -383,6 +384,13 @@ public class NotificationListenerServiceTest extends UiServiceTestCase {
return index % 3 == 0;
}
+ public static String getSummarization(int index) {
+ if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization())) {
+ return "summary " + index;
+ }
+ return null;
+ }
+
private boolean isBubble(int index) {
return index % 4 == 0;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java
index 9fe0e49c4ab8..09ebc23a1d7b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java
@@ -29,12 +29,19 @@ import android.os.UserHandle;
import android.service.notification.Adjustment;
import android.service.notification.StatusBarNotification;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+
import com.android.server.UiServiceTestCase;
+import org.junit.Rule;
import org.junit.Test;
public class NotificationRecordExtractorDataTest extends UiServiceTestCase {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Test
public void testHasDiffs_noDiffs() {
NotificationRecord r = generateRecord();
@@ -57,7 +64,8 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase {
r.getRankingScore(),
r.isConversation(),
r.getProposedImportance(),
- r.hasSensitiveContent());
+ r.hasSensitiveContent(),
+ r.getSummarization());
assertFalse(extractorData.hasDiffForRankingLocked(r, 1));
assertFalse(extractorData.hasDiffForLoggingLocked(r, 1));
@@ -85,7 +93,8 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase {
r.getRankingScore(),
r.isConversation(),
r.getProposedImportance(),
- r.hasSensitiveContent());
+ r.hasSensitiveContent(),
+ r.getSummarization());
Bundle signals = new Bundle();
signals.putInt(Adjustment.KEY_IMPORTANCE_PROPOSAL, IMPORTANCE_HIGH);
@@ -119,7 +128,8 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase {
r.getRankingScore(),
r.isConversation(),
r.getProposedImportance(),
- r.hasSensitiveContent());
+ r.hasSensitiveContent(),
+ r.getSummarization());
Bundle signals = new Bundle();
signals.putString(Adjustment.KEY_GROUP_KEY, "ranker_group");
@@ -154,7 +164,8 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase {
r.getRankingScore(),
r.isConversation(),
r.getProposedImportance(),
- r.hasSensitiveContent());
+ r.hasSensitiveContent(),
+ r.getSummarization());
Bundle signals = new Bundle();
signals.putBoolean(Adjustment.KEY_SENSITIVE_CONTENT, true);
@@ -166,6 +177,42 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase {
assertTrue(extractorData.hasDiffForLoggingLocked(r, 1));
}
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_NM_SUMMARIZATION)
+ public void testHasDiffs_summarization() {
+ NotificationRecord r = generateRecord();
+
+ NotificationRecordExtractorData extractorData = new NotificationRecordExtractorData(
+ 1,
+ r.getPackageVisibilityOverride(),
+ r.canShowBadge(),
+ r.canBubble(),
+ r.getNotification().isBubbleNotification(),
+ r.getChannel(),
+ r.getGroupKey(),
+ r.getPeopleOverride(),
+ r.getSnoozeCriteria(),
+ r.getUserSentiment(),
+ r.getSuppressedVisualEffects(),
+ r.getSystemGeneratedSmartActions(),
+ r.getSmartReplies(),
+ r.getImportance(),
+ r.getRankingScore(),
+ r.isConversation(),
+ r.getProposedImportance(),
+ r.hasSensitiveContent(),
+ r.getSummarization());
+
+ Bundle signals = new Bundle();
+ signals.putString(Adjustment.KEY_SUMMARIZATION, "SUMMARIZED!");
+ Adjustment adjustment = new Adjustment("pkg", r.getKey(), signals, "", 0);
+ r.addAdjustment(adjustment);
+ r.applyAdjustments();
+
+ assertTrue(extractorData.hasDiffForRankingLocked(r, 1));
+ assertTrue(extractorData.hasDiffForLoggingLocked(r, 1));
+ }
+
private NotificationRecord generateRecord() {
NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
final Notification.Builder builder = new Notification.Builder(getContext())
diff --git a/services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java b/services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java
index 038e1357159b..036e03c60091 100644
--- a/services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java
@@ -23,6 +23,7 @@ import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAV
import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE;
import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.Presubmit;
import android.view.ViewConfiguration;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -38,6 +39,7 @@ import org.junit.runner.RunWith;
* Build/Install/Run:
* atest WmTests:CombinationKeyTests
*/
+@Presubmit
@MediumTest
@RunWith(AndroidJUnit4.class)
@DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER_MULTI_KEY_GESTURES)
diff --git a/services/tests/wmtests/src/com/android/server/policy/DeferredKeyActionExecutorTests.java b/services/tests/wmtests/src/com/android/server/policy/DeferredKeyActionExecutorTests.java
index ca3787ec4546..bccdd67d33ed 100644
--- a/services/tests/wmtests/src/com/android/server/policy/DeferredKeyActionExecutorTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/DeferredKeyActionExecutorTests.java
@@ -19,6 +19,7 @@ package com.android.server.policy;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.Presubmit;
import android.view.KeyEvent;
import org.junit.Before;
@@ -29,6 +30,7 @@ import org.junit.Test;
*
* <p>Build/Install/Run: atest WmTests:DeferredKeyActionExecutorTests
*/
+@Presubmit
public final class DeferredKeyActionExecutorTests {
private DeferredKeyActionExecutor mKeyActionExecutor;
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java
index 8b5f68a1e974..a912c177c863 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java
@@ -29,6 +29,7 @@ import static org.testng.Assert.assertTrue;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
import android.view.KeyEvent;
import androidx.test.filters.SmallTest;
@@ -45,7 +46,7 @@ import java.util.concurrent.TimeUnit;
* Build/Install/Run:
* atest KeyCombinationManagerTests
*/
-
+@Presubmit
@SmallTest
public class KeyCombinationManagerTests {
private KeyCombinationManager mKeyCombinationManager;
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 85ef466b2477..16c786b52655 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
@@ -544,17 +544,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
}
@Test
- public void testKeyGestureSplitscreenFocus() {
- Assert.assertTrue(sendKeyGestureEventComplete(
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT));
- mPhoneWindowManager.assertSetSplitscreenFocus(true);
-
- Assert.assertTrue(sendKeyGestureEventComplete(
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT));
- mPhoneWindowManager.assertSetSplitscreenFocus(false);
- }
-
- @Test
public void testKeyGestureShortcutHelper() {
Assert.assertTrue(sendKeyGestureEventComplete(
KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER));
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java
index 82a5add407f4..d961a6acc9c1 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutManagerTests.java
@@ -42,6 +42,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
+import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
@@ -64,7 +65,7 @@ import java.util.Collections;
* Build/Install/Run:
* atest ModifierShortcutManagerTests
*/
-
+@Presubmit
@SmallTest
@EnableFlags(com.android.hardware.input.Flags.FLAG_MODIFIER_SHORTCUT_MANAGER_REFACTOR)
public class ModifierShortcutManagerTests {
@@ -127,7 +128,7 @@ public class ModifierShortcutManagerTests {
// Total valid shortcuts.
KeyboardShortcutGroup group =
mModifierShortcutManager.getApplicationLaunchKeyboardShortcuts(-1);
- assertEquals(13, group.getItems().size());
+ assertEquals(11, group.getItems().size());
// Total valid shift shortcuts.
assertEquals(3, group.getItems().stream()
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index af3dc1da4dcc..c73ce23fe6b5 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -48,6 +48,7 @@ import android.app.AppOpsManager;
import android.content.Context;
import android.hardware.input.InputManager;
import android.os.PowerManager;
+import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.filters.SmallTest;
@@ -72,6 +73,7 @@ import org.junit.Test;
* Build/Install/Run:
* atest WmTests:PhoneWindowManagerTests
*/
+@Presubmit
@SmallTest
public class PhoneWindowManagerTests {
diff --git a/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
index 33ccec3f785a..53e82bad818d 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
@@ -28,6 +28,7 @@ import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_POWER_GO_
import static org.junit.Assert.assertEquals;
import android.platform.test.annotations.EnableFlags;
+import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.view.Display;
@@ -40,6 +41,7 @@ import org.junit.Test;
* Build/Install/Run:
* atest WmTests:PowerKeyGestureTests
*/
+@Presubmit
public class PowerKeyGestureTests extends ShortcutKeyTestBase {
@Before
public void setUp() {
diff --git a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
index 08eb1451bd6f..6c6594220bad 100644
--- a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
@@ -39,6 +39,7 @@ import android.os.Process;
import android.os.SystemClock;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
+import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.KeyEvent;
@@ -57,6 +58,7 @@ import java.util.concurrent.TimeUnit;
* Build/Install/Run:
* atest WmTests:SingleKeyGestureTests
*/
+@Presubmit
public class SingleKeyGestureTests {
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
diff --git a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
index 3ea3235df0f4..833dd5d768e4 100644
--- a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
@@ -35,6 +35,7 @@ import android.app.ActivityTaskManager.RootTaskInfo;
import android.content.ComponentName;
import android.hardware.input.KeyGestureEvent;
import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.view.Display;
@@ -47,6 +48,7 @@ import org.junit.Test;
* Build/Install/Run:
* atest WmTests:StemKeyGestureTests
*/
+@Presubmit
public class StemKeyGestureTests extends ShortcutKeyTestBase {
private static final String TEST_TARGET_ACTIVITY = "com.android.server.policy/.TestActivity";
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 4ff3d433632a..f88492477487 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -925,11 +925,6 @@ class TestPhoneWindowManager {
verify(mStatusBarManagerInternal).moveFocusedTaskToStageSplit(anyInt(), eq(leftOrTop));
}
- void assertSetSplitscreenFocus(boolean leftOrTop) {
- mTestLooper.dispatchAll();
- verify(mStatusBarManagerInternal).setSplitscreenFocus(eq(leftOrTop));
- }
-
void assertStatusBarStartAssist() {
mTestLooper.dispatchAll();
verify(mStatusBarManagerInternal).startAssist(any());
diff --git a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
index 3ca352cfa60d..9e59bced01f1 100644
--- a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
@@ -57,6 +57,7 @@ import android.content.res.Resources;
import android.os.PowerManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
+import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.view.Display;
@@ -83,6 +84,7 @@ import java.util.function.BooleanSupplier;
*
* <p>Build/Install/Run: atest WmTests:WindowWakeUpPolicyTests
*/
+@Presubmit
public final class WindowWakeUpPolicyTests {
@Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index b32379ae4b1e..4d9df4666016 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -415,4 +415,5 @@ interface ITelecomService {
*/
boolean hasForegroundServiceDelegation(in PhoneAccountHandle phoneAccountHandle,
String callingPackage);
+ void setMetricsTestMode(boolean enabled);
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
index 9d9cac9702bb..d62fd63aeda6 100644
--- a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
@@ -22,8 +22,10 @@ import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Rlog;
import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -220,7 +222,7 @@ public final class SatelliteSubscriberInfo implements Parcelable {
StringBuilder sb = new StringBuilder();
sb.append("SubscriberId:");
- sb.append(mSubscriberId);
+ sb.append(Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mSubscriberId));
sb.append(",");
sb.append("CarrierId:");
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
index fb4f89ded547..75d3ec6d3fe6 100644
--- a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
@@ -21,8 +21,10 @@ import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Rlog;
import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.util.Objects;
@@ -132,7 +134,7 @@ public final class SatelliteSubscriberProvisionStatus implements Parcelable {
StringBuilder sb = new StringBuilder();
sb.append("SatelliteSubscriberInfo:");
- sb.append(mSubscriberInfo);
+ sb.append(Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mSubscriberInfo));
sb.append(",");
sb.append("ProvisionStatus:");
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/RecentTasksUtils.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/RecentTasksUtils.kt
index aa262f9dfd6a..1a5fda7c8324 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/RecentTasksUtils.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/RecentTasksUtils.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.flicker.utils
+package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
@@ -24,4 +24,4 @@ object RecentTasksUtils {
"dumpsys activity service SystemUIService WMShell recents clearAll"
)
}
-} \ No newline at end of file
+}
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index e0532633d40b..eef4e6f58463 100644
--- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -467,30 +467,6 @@ class KeyGestureControllerTests {
intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
),
TestData(
- "CTRL + ALT + DPAD_LEFT -> Change Splitscreen Focus Left",
- intArrayOf(
- KeyEvent.KEYCODE_CTRL_LEFT,
- KeyEvent.KEYCODE_ALT_LEFT,
- KeyEvent.KEYCODE_DPAD_LEFT
- ),
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT,
- intArrayOf(KeyEvent.KEYCODE_DPAD_LEFT),
- KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
- intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
- ),
- TestData(
- "CTRL + ALT + DPAD_RIGHT -> Change Splitscreen Focus Right",
- intArrayOf(
- KeyEvent.KEYCODE_CTRL_LEFT,
- KeyEvent.KEYCODE_ALT_LEFT,
- KeyEvent.KEYCODE_DPAD_RIGHT
- ),
- KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT,
- intArrayOf(KeyEvent.KEYCODE_DPAD_RIGHT),
- KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
- intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
- ),
- TestData(
"META + / -> Open Shortcut Helper",
intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_SLASH),
KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER,