summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/android/os/TracePerfTest.java4
-rw-r--r--apct-tests/perftests/healthconnect/OWNERS1
-rw-r--r--api/OWNERS1
-rw-r--r--cmds/idmap2/OWNERS1
-rw-r--r--core/api/current.txt8
-rw-r--r--core/api/test-current.txt6
-rw-r--r--core/java/android/app/ActivityManager.java40
-rw-r--r--core/java/android/app/ActivityOptions.java25
-rw-r--r--core/java/android/app/ContextImpl.java45
-rw-r--r--core/java/android/app/DreamManager.java7
-rw-r--r--core/java/android/app/Notification.java9
-rw-r--r--core/java/android/app/PropertyInvalidatedCache.java26
-rw-r--r--core/java/android/app/admin/PolicyUpdateReceiver.java31
-rw-r--r--core/java/android/app/contextualsearch/flags.aconfig12
-rw-r--r--core/java/android/app/performance.aconfig7
-rw-r--r--core/java/android/app/servertransaction/ClientTransaction.java12
-rw-r--r--core/java/android/content/integrity/OWNERS1
-rw-r--r--core/java/android/content/pm/flags.aconfig8
-rw-r--r--core/java/android/content/pm/parsing/OWNERS2
-rw-r--r--core/java/android/content/pm/permission/OWNERS1
-rw-r--r--core/java/android/gesture/OWNERS1
-rw-r--r--core/java/android/metrics/OWNERS1
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/os/CombinedMessageQueue/MessageQueue.java13
-rw-r--r--core/java/android/os/IBinder.java2
-rw-r--r--core/java/android/os/IpcDataCache.java10
-rw-r--r--core/java/android/os/Looper.java2
-rw-r--r--core/java/android/os/Message.java4
-rw-r--r--core/java/android/os/OWNERS2
-rw-r--r--core/java/android/os/PerfettoTrackEventExtra.java40
-rw-r--r--core/java/android/os/PowerManagerInternal.java5
-rw-r--r--core/java/android/permission/PermissionManager.java40
-rw-r--r--core/java/android/preference/OWNERS3
-rw-r--r--core/java/android/print/OWNERS1
-rw-r--r--core/java/android/printservice/OWNERS1
-rw-r--r--core/java/android/security/advancedprotection/AdvancedProtectionManager.java8
-rw-r--r--core/java/android/service/dreams/IDreamManager.aidl2
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java7
-rw-r--r--core/java/android/text/OWNERS1
-rw-r--r--core/java/android/util/apk/OWNERS1
-rw-r--r--core/java/android/view/OWNERS1
-rw-r--r--core/java/android/view/SurfaceView.java21
-rw-r--r--core/java/android/view/View.java11
-rw-r--r--core/java/android/view/ViewRootImpl.java65
-rw-r--r--core/java/android/view/ViewStructure.java13
-rw-r--r--core/java/android/view/WindowManager.java7
-rw-r--r--core/java/android/view/inspector/OWNERS1
-rw-r--r--core/java/android/webkit/TEST_MAPPING9
-rw-r--r--core/java/android/webkit/WebSettings.java7
-rw-r--r--core/java/android/webkit/WebView.java57
-rw-r--r--core/java/android/window/DesktopModeFlags.java4
-rw-r--r--core/java/android/window/TransitionInfo.java4
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig12
-rw-r--r--core/java/android/window/flags/windowing_sdk.aconfig13
-rw-r--r--core/java/com/android/internal/config/appcloning/OWNERS1
-rw-r--r--core/java/com/android/internal/infra/OWNERS6
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistory.java14
-rw-r--r--core/java/com/android/internal/util/OWNERS4
-rw-r--r--core/java/com/android/internal/util/function/pooled/OWNERS1
-rw-r--r--core/java/com/android/internal/widget/ConversationLayout.java3
-rw-r--r--core/java/com/android/internal/widget/MessagingLayout.java3
-rw-r--r--core/java/com/android/internal/widget/remotecompose/OWNERS1
-rw-r--r--core/jni/Android.bp4
-rw-r--r--core/jni/com_android_internal_content_NativeLibraryHelper.cpp4
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--core/res/OWNERS1
-rw-r--r--core/res/res/layout/accessibility_autoclick_type_panel.xml4
-rw-r--r--core/res/res/values/locale_config.xml10
-rw-r--r--core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java25
-rw-r--r--core/tests/coretests/src/android/content/pm/OWNERS1
-rw-r--r--core/tests/coretests/src/android/os/IpcDataCacheTest.java26
-rw-r--r--core/tests/coretests/src/android/view/ViewRootImplTest.java115
-rw-r--r--core/tests/featureflagtests/OWNERS3
-rw-r--r--data/etc/OWNERS1
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--drm/java/android/drm/OWNERS1
-rw-r--r--graphics/java/android/graphics/Paint.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java98
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt46
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt217
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/OWNERS1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java47
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java45
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/OWNERS1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java6
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt71
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt19
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt56
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt205
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/OWNERS3
-rw-r--r--libs/hwui/OWNERS2
-rw-r--r--location/java/com/android/internal/location/GpsNetInitiatedHandler.java3
-rw-r--r--media/java/android/media/MediaCodecInfo.java9
-rw-r--r--media/java/android/media/MediaExtractor.java7
-rw-r--r--media/java/android/media/Utils.java34
-rw-r--r--media/jni/OWNERS2
-rw-r--r--native/webview/TEST_MAPPING9
-rw-r--r--opengl/java/android/opengl/OWNERS1
-rw-r--r--packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml1
-rw-r--r--packages/SettingsLib/OWNERS1
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background.xml8
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom.xml8
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_highlighted.xml6
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_selected.xml8
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center.xml5
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_highlighted.xml5
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_selected.xml5
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_highlighted.xml6
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_selected.xml8
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top.xml5
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_highlighted.xml5
-rw-r--r--packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_selected.xml5
-rw-r--r--packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/NormalPaddingMixin.kt25
-rw-r--r--packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsBasePreferenceFragment.kt17
-rw-r--r--packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt22
-rw-r--r--packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java26
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS1
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java15
-rw-r--r--packages/Shell/OWNERS3
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt22
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt231
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt17
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt9
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt33
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java8
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java18
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java76
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt115
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt44
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt173
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt97
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java19
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt50
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/ConversationNotificationProcessorTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt7
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt39
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt148
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt8
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt36
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt4
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt20
-rw-r--r--packages/SystemUI/res/layout/volume_dialog_top_section.xml1
-rw-r--r--packages/SystemUI/res/values/strings.xml6
-rw-r--r--packages/SystemUI/res/values/styles.xml1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt94
-rw-r--r--packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt124
-rw-r--r--packages/SystemUI/src/com/android/systemui/grid/ui/compose/SpannedGrids.kt141
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java5
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt39
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt2
-rw-r--r--proto/src/metrics_constants/OWNERS2
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java12
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java12
-rw-r--r--ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt29
-rw-r--r--ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt15
-rw-r--r--ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt7
-rw-r--r--ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapperFilter.kt10
-rw-r--r--ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt101
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt117
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt166
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt218
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt117
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt166
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt218
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt4
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java17
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java5
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java4
-rw-r--r--ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java11
-rw-r--r--ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt1
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java29
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickLinearLayout.java80
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java18
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java11
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java49
-rw-r--r--services/core/java/com/android/server/appop/DiscreteOpsRegistry.java2
-rw-r--r--services/core/java/com/android/server/appop/DiscreteOpsSqlRegistry.java113
-rw-r--r--services/core/java/com/android/server/appop/HistoricalRegistry.java1
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java4
-rw-r--r--services/core/java/com/android/server/display/mode/ModeChangeObserver.java3
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java15
-rw-r--r--services/core/java/com/android/server/input/InputDataStore.java4
-rw-r--r--services/core/java/com/android/server/inputmethod/OWNERS1
-rw-r--r--services/core/java/com/android/server/pm/BackgroundInstallControlService.java7
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java4
-rw-r--r--services/core/java/com/android/server/pm/InstallRequest.java12
-rw-r--r--services/core/java/com/android/server/pm/OWNERS1
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java8
-rw-r--r--services/core/java/com/android/server/pm/PackageMetrics.java4
-rw-r--r--services/core/java/com/android/server/pm/dex/OWNERS1
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java7
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryHistoryDirectory.java4
-rw-r--r--services/core/java/com/android/server/uri/OWNERS1
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java11
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java4
-rw-r--r--services/core/java/com/android/server/wm/BackgroundActivityStartController.java93
-rw-r--r--services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java10
-rw-r--r--services/core/java/com/android/server/wm/ClientLifecycleManager.java102
-rw-r--r--services/core/java/com/android/server/wm/ContentRecorder.java2
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java96
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java9
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java16
-rw-r--r--services/core/java/com/android/server/wm/KeyguardController.java29
-rw-r--r--services/core/java/com/android/server/wm/OWNERS1
-rw-r--r--services/core/java/com/android/server/wm/Transition.java5
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java13
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java25
-rw-r--r--services/core/jni/stats/OWNERS1
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java93
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java9
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceMockedTest.java (renamed from services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java)7
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java89
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickLinearLayoutTest.java102
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java43
-rw-r--r--services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpSqlPersistenceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/appop/DiscreteOpsMigrationAndRollbackTest.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerLogTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java76
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java107
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java3
-rw-r--r--telecomm/java/android/telecom/OWNERS1
-rw-r--r--tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java16
-rw-r--r--tests/EnforcePermission/OWNERS1
-rw-r--r--tools/codegen/OWNERS1
-rw-r--r--tools/hiddenapi/OWNERS1
-rw-r--r--tools/lint/OWNERS1
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS1
277 files changed, 4614 insertions, 2045 deletions
diff --git a/apct-tests/perftests/core/src/android/os/TracePerfTest.java b/apct-tests/perftests/core/src/android/os/TracePerfTest.java
index d9051240d399..00e1c1fdbf4b 100644
--- a/apct-tests/perftests/core/src/android/os/TracePerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/TracePerfTest.java
@@ -147,7 +147,7 @@ public class TracePerfTest {
.addField(1 /* sending_thread_name */, "foo")
.endNested()
.endProto()
- .addTerminatingFlow(5)
+ .setTerminatingFlow(5)
.emit();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
@@ -158,7 +158,7 @@ public class TracePerfTest {
.addField(1 /* sending_thread_name */, "foo")
.endNested()
.endProto()
- .addTerminatingFlow(5)
+ .setTerminatingFlow(5)
.emit();
}
}
diff --git a/apct-tests/perftests/healthconnect/OWNERS b/apct-tests/perftests/healthconnect/OWNERS
index acfe799314ec..7c9e7692a9fc 100644
--- a/apct-tests/perftests/healthconnect/OWNERS
+++ b/apct-tests/perftests/healthconnect/OWNERS
@@ -1,5 +1,4 @@
# Bug component: 1219472
-arkivanov@google.com
jstembridge@google.com
itsleo@google.com
diff --git a/api/OWNERS b/api/OWNERS
index f2bcf13d2d2e..31ffa8cd4e9f 100644
--- a/api/OWNERS
+++ b/api/OWNERS
@@ -1,4 +1,3 @@
-hansson@google.com
# Modularization team
file:platform/packages/modules/common:/OWNERS
diff --git a/cmds/idmap2/OWNERS b/cmds/idmap2/OWNERS
index 062ffd41348a..def9f401e51f 100644
--- a/cmds/idmap2/OWNERS
+++ b/cmds/idmap2/OWNERS
@@ -1,4 +1,3 @@
set noparent
-toddke@google.com
patb@google.com
zyy@google.com
diff --git a/core/api/current.txt b/core/api/current.txt
index 13127537e6d9..3da5a5cca861 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -16993,7 +16993,7 @@ package android.graphics {
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(String);
- method @FlaggedApi("com.android.text.flags.typeface_redesign_readonly") public boolean setFontVariationOverride(@Nullable String);
+ method @FlaggedApi("com.android.text.flags.typeface_redesign_readonly") public void setFontVariationOverride(@Nullable String);
method public boolean setFontVariationSettings(String);
method public void setHinting(int);
method public void setLetterSpacing(float);
@@ -23332,12 +23332,12 @@ package android.media {
public static final class MediaCodecInfo.CodecCapabilities {
ctor public MediaCodecInfo.CodecCapabilities();
method public static android.media.MediaCodecInfo.CodecCapabilities createFromProfileLevel(String, int, int);
- method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
+ method @Nullable public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
method public android.media.MediaFormat getDefaultFormat();
- method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
+ method @Nullable public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
method public int getMaxSupportedInstances();
method public String getMimeType();
- method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
+ method @Nullable public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
method public boolean isFeatureRequired(String);
method public boolean isFeatureSupported(String);
method public boolean isFormatSupported(android.media.MediaFormat);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 514a58244aa2..00ec48b79541 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2128,6 +2128,12 @@ package android.media {
method public android.media.PlaybackParams setAudioStretchMode(int);
}
+ public class Utils {
+ ctor public Utils();
+ field public static final String SYNCHRONIZED_VIBRATION = "synchronized";
+ field public static final String VIBRATION_URI_PARAM = "vibration_uri";
+ }
+
public final class VolumePolicy implements android.os.Parcelable {
ctor public VolumePolicy(boolean, boolean, boolean, int);
method public int describeContents();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 69d3e8d4c0d2..f9ec214390f9 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -550,35 +550,35 @@ public class ActivityManager {
public static final int START_ASSISTANT_NOT_ACTIVE_SESSION = FIRST_START_FATAL_ERROR_CODE + 11;
/**
- * Result for IActivityManaqer.startActivity: the activity was started
+ * Result for IActivityManager.startActivity: the activity was started
* successfully as normal.
* @hide
*/
public static final int START_SUCCESS = FIRST_START_SUCCESS_CODE;
/**
- * Result for IActivityManaqer.startActivity: the caller asked that the Intent not
+ * Result for IActivityManager.startActivity: the caller asked that the Intent not
* be executed if it is the recipient, and that is indeed the case.
* @hide
*/
public static final int START_RETURN_INTENT_TO_CALLER = FIRST_START_SUCCESS_CODE + 1;
/**
- * Result for IActivityManaqer.startActivity: activity was started or brought forward in an
+ * Result for IActivityManager.startActivity: activity was started or brought forward in an
* existing task which was brought to the foreground.
* @hide
*/
public static final int START_TASK_TO_FRONT = FIRST_START_SUCCESS_CODE + 2;
/**
- * Result for IActivityManaqer.startActivity: activity wasn't really started, but
+ * Result for IActivityManager.startActivity: activity wasn't really started, but
* the given Intent was given to the existing top activity.
* @hide
*/
public static final int START_DELIVERED_TO_TOP = FIRST_START_SUCCESS_CODE + 3;
/**
- * Result for IActivityManaqer.startActivity: request was canceled because
+ * Result for IActivityManager.startActivity: request was canceled because
* app switches are temporarily canceled to ensure the user's last request
* (such as pressing home) is performed.
* @hide
@@ -586,7 +586,7 @@ public class ActivityManager {
public static final int START_SWITCHES_CANCELED = FIRST_START_NON_FATAL_ERROR_CODE;
/**
- * Result for IActivityManaqer.startActivity: a new activity was attempted to be started
+ * Result for IActivityManager.startActivity: a new activity was attempted to be started
* while in Lock Task Mode.
* @hide
*/
@@ -594,55 +594,55 @@ public class ActivityManager {
FIRST_START_NON_FATAL_ERROR_CODE + 1;
/**
- * Result for IActivityManaqer.startActivity: a new activity start was aborted. Never returned
+ * Result for IActivityManager.startActivity: a new activity start was aborted. Never returned
* externally.
* @hide
*/
public static final int START_ABORTED = FIRST_START_NON_FATAL_ERROR_CODE + 2;
/**
- * Flag for IActivityManaqer.startActivity: do special start mode where
+ * Flag for IActivityManager.startActivity: do special start mode where
* a new activity is launched only if it is needed.
* @hide
*/
public static final int START_FLAG_ONLY_IF_NEEDED = 1<<0;
/**
- * Flag for IActivityManaqer.startActivity: launch the app for
+ * Flag for IActivityManager.startActivity: launch the app for
* debugging.
* @hide
*/
public static final int START_FLAG_DEBUG = 1<<1;
/**
- * Flag for IActivityManaqer.startActivity: launch the app for
+ * Flag for IActivityManager.startActivity: launch the app for
* allocation tracking.
* @hide
*/
public static final int START_FLAG_TRACK_ALLOCATION = 1<<2;
/**
- * Flag for IActivityManaqer.startActivity: launch the app with
+ * Flag for IActivityManager.startActivity: launch the app with
* native debugging support.
* @hide
*/
public static final int START_FLAG_NATIVE_DEBUGGING = 1<<3;
/**
- * Flag for IActivityManaqer.startActivity: launch the app for
+ * Flag for IActivityManager.startActivity: launch the app for
* debugging and suspend threads.
* @hide
*/
public static final int START_FLAG_DEBUG_SUSPEND = 1 << 4;
/**
- * Result for IActivityManaqer.broadcastIntent: success!
+ * Result for IActivityManager.broadcastIntent: success!
* @hide
*/
public static final int BROADCAST_SUCCESS = 0;
/**
- * Result for IActivityManaqer.broadcastIntent: attempt to broadcast
+ * Result for IActivityManager.broadcastIntent: attempt to broadcast
* a sticky intent without appropriate permission.
* @hide
*/
@@ -656,20 +656,20 @@ public class ActivityManager {
public static final int BROADCAST_FAILED_USER_STOPPED = -2;
/**
- * Type for IActivityManaqer.getIntentSender: this PendingIntent type is unknown.
+ * Type for IActivityManager.getIntentSender: this PendingIntent type is unknown.
* @hide
*/
public static final int INTENT_SENDER_UNKNOWN = 0;
/**
- * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+ * Type for IActivityManager.getIntentSender: this PendingIntent is
* for a sendBroadcast operation.
* @hide
*/
public static final int INTENT_SENDER_BROADCAST = 1;
/**
- * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+ * Type for IActivityManager.getIntentSender: this PendingIntent is
* for a startActivity operation.
* @hide
*/
@@ -677,21 +677,21 @@ public class ActivityManager {
public static final int INTENT_SENDER_ACTIVITY = 2;
/**
- * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+ * Type for IActivityManager.getIntentSender: this PendingIntent is
* for an activity result operation.
* @hide
*/
public static final int INTENT_SENDER_ACTIVITY_RESULT = 3;
/**
- * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+ * Type for IActivityManager.getIntentSender: this PendingIntent is
* for a startService operation.
* @hide
*/
public static final int INTENT_SENDER_SERVICE = 4;
/**
- * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+ * Type for IActivityManager.getIntentSender: this PendingIntent is
* for a startForegroundService operation.
* @hide
*/
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index b8c20bd97264..cc3745675bc9 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -488,6 +488,8 @@ public class ActivityOptions extends ComponentOptions {
private static final String KEY_ALLOW_PASS_THROUGH_ON_TOUCH_OUTSIDE =
"android.activity.allowPassThroughOnTouchOutside";
+ private static final String KEY_FLEXIBLE_LAUNCH_SIZE = "android.activity.flexibleLaunchSize";
+
/**
* @see #setLaunchCookie
* @hide
@@ -588,6 +590,7 @@ public class ActivityOptions extends ComponentOptions {
@BackgroundActivityStartMode
private int mPendingIntentCreatorBackgroundActivityStartMode =
MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
+ private boolean mFlexibleLaunchSize = false;
private boolean mDisableStartingWindow;
private boolean mAllowPassThroughOnTouchOutside;
@@ -1451,6 +1454,7 @@ public class ActivityOptions extends ComponentOptions {
mPendingIntentCreatorBackgroundActivityStartMode = opts.getInt(
KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE,
MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED);
+ mFlexibleLaunchSize = opts.getBoolean(KEY_FLEXIBLE_LAUNCH_SIZE, /* defaultValue = */ false);
mDisableStartingWindow = opts.getBoolean(KEY_DISABLE_STARTING_WINDOW);
mAllowPassThroughOnTouchOutside = opts.getBoolean(KEY_ALLOW_PASS_THROUGH_ON_TOUCH_OUTSIDE);
mAnimationAbortListener = IRemoteCallback.Stub.asInterface(
@@ -2346,6 +2350,24 @@ public class ActivityOptions extends ComponentOptions {
}
/**
+ * Sets whether the size of the launch bounds is flexible, meaning it can be overridden to a
+ * different size during the launch params calculation.
+ * @hide
+ */
+ public ActivityOptions setFlexibleLaunchSize(boolean isFlexible) {
+ mFlexibleLaunchSize = isFlexible;
+ return this;
+ }
+
+ /**
+ * Gets whether the size of the launch bounds is flexible.
+ * @hide
+ */
+ public boolean getFlexibleLaunchSize() {
+ return mFlexibleLaunchSize;
+ }
+
+ /**
* Update the current values in this ActivityOptions from those supplied
* in <var>otherOptions</var>. Any values
* defined in <var>otherOptions</var> replace those in the base options.
@@ -2601,6 +2623,9 @@ public class ActivityOptions extends ComponentOptions {
b.putInt(KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE,
mPendingIntentCreatorBackgroundActivityStartMode);
}
+ if (mFlexibleLaunchSize) {
+ b.putBoolean(KEY_FLEXIBLE_LAUNCH_SIZE, mFlexibleLaunchSize);
+ }
if (mDisableStartingWindow) {
b.putBoolean(KEY_DISABLE_STARTING_WINDOW, mDisableStartingWindow);
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1a6e9b07067f..dc5974fde0b0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -22,14 +22,12 @@ import static android.os.StrictMode.vmIncorrectContextUseEnabled;
import static android.permission.flags.Flags.shouldRegisterAttributionSource;
import static android.view.WindowManager.LayoutParams.WindowType;
-import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.UiContext;
-import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AttributionSource;
@@ -2367,47 +2365,11 @@ class ContextImpl extends Context {
Log.v(TAG, "Treating renounced permission " + permission + " as denied");
return PERMISSION_DENIED;
}
- int deviceId = resolveDeviceIdForPermissionCheck(permission);
+ int deviceId = PermissionManager.resolveDeviceIdForPermissionCheck(this, getDeviceId(),
+ permission);
return PermissionManager.checkPermission(permission, pid, uid, deviceId);
}
- private int resolveDeviceIdForPermissionCheck(String permission) {
- // When checking a device-aware permission on a remote device, if the permission is CAMERA
- // or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote
- // device doesn't have capability fall back to checking permission on the default device.
- // Note: we only perform permission check redirection when the device id is not explicitly
- // set in the context.
- int deviceId = getDeviceId();
- if (deviceId != Context.DEVICE_ID_DEFAULT
- && !mIsExplicitDeviceId
- && PermissionManager.DEVICE_AWARE_PERMISSIONS.contains(permission)) {
- VirtualDeviceManager virtualDeviceManager =
- getSystemService(VirtualDeviceManager.class);
- if (virtualDeviceManager == null) {
- Slog.e(
- TAG,
- "VDM is not enabled when device id is not default. deviceId = "
- + deviceId);
- } else {
- VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
- if (virtualDevice != null) {
- if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO)
- && !virtualDevice.hasCustomAudioInputSupport())
- || (Objects.equals(permission, Manifest.permission.CAMERA)
- && !virtualDevice.hasCustomCameraSupport())) {
- deviceId = Context.DEVICE_ID_DEFAULT;
- }
- } else {
- Slog.e(
- TAG,
- "virtualDevice is not found when device id is not default. deviceId = "
- + deviceId);
- }
- }
- }
- return deviceId;
- }
-
/** @hide */
@Override
public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
@@ -2511,7 +2473,8 @@ class ContextImpl extends Context {
@Override
public int getPermissionRequestState(String permission) {
Objects.requireNonNull(permission, "Permission name can't be null");
- int deviceId = resolveDeviceIdForPermissionCheck(permission);
+ int deviceId = PermissionManager.resolveDeviceIdForPermissionCheck(this, getDeviceId(),
+ permission);
PermissionManager permissionManager = getSystemService(PermissionManager.class);
return permissionManager.getPermissionRequestState(getOpPackageName(), permission,
deviceId);
diff --git a/core/java/android/app/DreamManager.java b/core/java/android/app/DreamManager.java
index c597a9dcae7e..555006b97911 100644
--- a/core/java/android/app/DreamManager.java
+++ b/core/java/android/app/DreamManager.java
@@ -71,8 +71,11 @@ public class DreamManager {
@TestApi
@RequiresPermission(WRITE_SECURE_SETTINGS)
public void setScreensaverEnabled(boolean enabled) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.SCREENSAVER_ENABLED, enabled ? 1 : 0, UserHandle.USER_CURRENT);
+ try {
+ mService.setScreensaverEnabled(enabled);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
}
/**
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1b71e73db852..cc72d8f1ad8c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -9526,14 +9526,21 @@ public class Notification implements Parcelable
.viewType(viewType)
.highlightExpander(isConversationLayout)
.hideProgress(true)
- .text(null)
.hideLeftIcon(isOneToOne)
.hideRightIcon(hideRightIcons || isOneToOne);
if (notificationsRedesignTemplates()) {
+ String lastMessage = !mMessages.isEmpty()
+ ? mMessages.getLast().mText.toString() : null;
+
p.title(conversationTitle)
+ // The text is not actually displayed like this (since we're using a
+ // MessagingLinearLayout instead of the regular text), but we're using it to
+ // know whether the notification will have a second line in practice.
+ .text(lastMessage)
.hideAppName(isCollapsed);
} else {
p.title(isLegacyHeaderless ? conversationTitle : null)
+ .text(null)
.headerTextSecondary(isLegacyHeaderless ? null : conversationTitle);
}
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index c573161f30cc..38141cf20ce3 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -293,6 +293,7 @@ public class PropertyInvalidatedCache<Query, Result> {
// The test mode. This is only used to ensure that the test functions setTestMode() and
// testPropertyName() are used correctly.
+ @GuardedBy("sGlobalLock")
private static boolean sTestMode = false;
/**
@@ -668,7 +669,7 @@ public class PropertyInvalidatedCache<Query, Result> {
// True if this handler is in test mode. If it is in test mode, then nonces are stored
// and retrieved from mTestNonce.
@GuardedBy("mLock")
- private boolean mTestMode = false;
+ private boolean mTestMode;
// This is the local value of the nonce, as last set by the NonceHandler. It is always
// updated by the setNonce() operation. The getNonce() operation returns this value in
@@ -692,6 +693,9 @@ public class PropertyInvalidatedCache<Query, Result> {
NonceHandler(@NonNull String name) {
mName = name;
+ synchronized (sGlobalLock) {
+ mTestMode = sTestMode;
+ }
}
/**
@@ -1414,9 +1418,13 @@ public class PropertyInvalidatedCache<Query, Result> {
/**
* Enable or disable testing. The protocol requires that the mode toggle: for instance, it is
- * illegal to clear the test mode if the test mode is already off. The purpose is solely to
- * ensure that test clients do not forget to use the test mode properly, even though the
- * current logic does not care.
+ * illegal to clear the test mode if the test mode is already off. Enabling test mode puts
+ * all caches in the process into test mode; all nonces are initialized to UNSET and
+ * subsequent reads and writes are to process memory. This has the effect of disabling all
+ * caches that are not local to the process. Disabling test mode restores caches to normal
+ * operation.
+ * @param mode The desired test mode.
+ * @throws IllegalStateException if the supplied mode is already set.
* @hide
*/
@VisibleForTesting
@@ -1431,10 +1439,8 @@ public class PropertyInvalidatedCache<Query, Result> {
}
}
sTestMode = mode;
- if (mode) {
- // No action when testing begins.
- } else {
- resetAfterTestLocked();
+ if (Flags.picTestMode() || !mode) {
+ setTestModeLocked(mode);
}
}
}
@@ -1445,11 +1451,11 @@ public class PropertyInvalidatedCache<Query, Result> {
* that were not originally in test mode.
*/
@GuardedBy("sGlobalLock")
- private static void resetAfterTestLocked() {
+ private static void setTestModeLocked(boolean mode) {
for (Iterator<String> e = sHandlers.keys().asIterator(); e.hasNext(); ) {
String s = e.next();
final NonceHandler h = sHandlers.get(s);
- h.setTestMode(false);
+ h.setTestMode(mode);
}
}
diff --git a/core/java/android/app/admin/PolicyUpdateReceiver.java b/core/java/android/app/admin/PolicyUpdateReceiver.java
index be13988d7c76..630ab0ece07d 100644
--- a/core/java/android/app/admin/PolicyUpdateReceiver.java
+++ b/core/java/android/app/admin/PolicyUpdateReceiver.java
@@ -20,10 +20,12 @@ import android.annotation.BroadcastBehavior;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.TestApi;
+import android.app.admin.flags.Flags;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
import java.util.Objects;
@@ -46,6 +48,10 @@ import java.util.Objects;
public abstract class PolicyUpdateReceiver extends BroadcastReceiver {
private static String TAG = "PolicyUpdateReceiver";
+ //TODO(b/378931989): Switch to android.app.admin.DevicePolicyIdentifiers.MEMORY_TAGGING_POLICY
+ //when the appropriate flag is launched.
+ private static final String MEMORY_TAGGING_POLICY = "memoryTagging";
+
/**
* Action for a broadcast sent to admins to communicate back the result of setting a policy in
* {@link DevicePolicyManager}.
@@ -156,15 +162,28 @@ public abstract class PolicyUpdateReceiver extends BroadcastReceiver {
@Override
public final void onReceive(Context context, Intent intent) {
Objects.requireNonNull(intent.getAction());
+ String policyKey;
switch (intent.getAction()) {
case ACTION_DEVICE_POLICY_SET_RESULT:
Log.i(TAG, "Received ACTION_DEVICE_POLICY_SET_RESULT");
- onPolicySetResult(context, getPolicyKey(intent), getPolicyExtraBundle(intent),
+ policyKey = getPolicyKey(intent);
+ if (!shouldPropagatePolicy(policyKey)) {
+ Log.d(TAG, TextUtils.formatSimple(
+ "Skipping propagation of policy %s", policyKey));
+ break;
+ }
+ onPolicySetResult(context, policyKey, getPolicyExtraBundle(intent),
getTargetUser(intent), getPolicyChangedReason(intent));
break;
case ACTION_DEVICE_POLICY_CHANGED:
Log.i(TAG, "Received ACTION_DEVICE_POLICY_CHANGED");
- onPolicyChanged(context, getPolicyKey(intent), getPolicyExtraBundle(intent),
+ policyKey = getPolicyKey(intent);
+ if (!shouldPropagatePolicy(policyKey)) {
+ Log.d(TAG, TextUtils.formatSimple(
+ "Skipping propagation of policy %s", policyKey));
+ break;
+ }
+ onPolicyChanged(context, policyKey, getPolicyExtraBundle(intent),
getTargetUser(intent), getPolicyChangedReason(intent));
break;
default:
@@ -217,6 +236,14 @@ public abstract class PolicyUpdateReceiver extends BroadcastReceiver {
return new TargetUser(targetUserId);
}
+ /**
+ * @hide
+ */
+ private boolean shouldPropagatePolicy(String policyKey) {
+ return !MEMORY_TAGGING_POLICY.equals(policyKey) || Flags.setMtePolicyCoexistence();
+ }
+
+
// TODO(b/260847505): Add javadocs to explain which DPM APIs are supported
/**
* Callback triggered after an admin has set a policy using one of the APIs in
diff --git a/core/java/android/app/contextualsearch/flags.aconfig b/core/java/android/app/contextualsearch/flags.aconfig
index 1de034b23a7a..1a14b20d6c09 100644
--- a/core/java/android/app/contextualsearch/flags.aconfig
+++ b/core/java/android/app/contextualsearch/flags.aconfig
@@ -23,6 +23,18 @@ flag {
bug: "371065456"
}
+
+flag {
+ name: "report_secure_surfaces_in_assist_structure"
+ namespace: "windowing_frontend"
+ description: "SurfaceView reports when the surface is using a SECURE flag."
+ bug: "390504528"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+
flag {
name: "contextual_search_prevent_self_capture"
namespace: "sysui_integrations"
diff --git a/core/java/android/app/performance.aconfig b/core/java/android/app/performance.aconfig
index 2569f7b99dca..82875ebb0f77 100644
--- a/core/java/android/app/performance.aconfig
+++ b/core/java/android/app/performance.aconfig
@@ -50,3 +50,10 @@ flag {
description: "Cache null returns from binder calls"
bug: "372923336"
}
+
+flag {
+ namespace: "system_performance"
+ name: "pic_test_mode"
+ description: "Updated test mode for PIC"
+ bug: "396173886"
+}
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 6e3e86cfbffc..e726bc9df4d5 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -236,9 +236,17 @@ public class ClientTransaction implements Parcelable {
* 2. The transaction message is scheduled.
* 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
* all callbacks and necessary lifecycle transitions.
+ *
+ * @return {@link RemoteException} if the transaction failed.
*/
- public void schedule() throws RemoteException {
- mClient.scheduleTransaction(this);
+ @Nullable
+ public RemoteException schedule() {
+ try {
+ mClient.scheduleTransaction(this);
+ return null;
+ } catch (RemoteException e) {
+ return e;
+ }
}
// Parcelable implementation
diff --git a/core/java/android/content/integrity/OWNERS b/core/java/android/content/integrity/OWNERS
index 20c758aedd67..ca65fdab99b1 100644
--- a/core/java/android/content/integrity/OWNERS
+++ b/core/java/android/content/integrity/OWNERS
@@ -1,5 +1,4 @@
# Bug component: 722021
toddke@android.com
-toddke@google.com
patb@google.com
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 255a08cf170f..42bef0e91539 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -400,3 +400,11 @@ flag {
bug: "378539511"
is_fixed_read_only: true
}
+
+flag {
+ name: "cloud_compilation_verification"
+ namespace: "art_mainline"
+ description: "Feature flag to enable the Cloud Compilation install-time verification in the package manager."
+ bug: "377474232"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/content/pm/parsing/OWNERS b/core/java/android/content/pm/parsing/OWNERS
index 8049d5cb7fa2..b8fa1a93ed78 100644
--- a/core/java/android/content/pm/parsing/OWNERS
+++ b/core/java/android/content/pm/parsing/OWNERS
@@ -1,5 +1,3 @@
# Bug component: 36137
-chiuwinson@google.com
patb@google.com
-toddke@google.com
diff --git a/core/java/android/content/pm/permission/OWNERS b/core/java/android/content/pm/permission/OWNERS
index cf7e6890876a..8ef84745c99f 100644
--- a/core/java/android/content/pm/permission/OWNERS
+++ b/core/java/android/content/pm/permission/OWNERS
@@ -3,6 +3,5 @@
include platform/frameworks/base:/core/java/android/permission/OWNERS
toddke@android.com
-toddke@google.com
patb@google.com
diff --git a/core/java/android/gesture/OWNERS b/core/java/android/gesture/OWNERS
index 168630af6da4..ffa753aa65b2 100644
--- a/core/java/android/gesture/OWNERS
+++ b/core/java/android/gesture/OWNERS
@@ -3,5 +3,4 @@
romainguy@google.com
adamp@google.com
aurimas@google.com
-nduca@google.com
sumir@google.com
diff --git a/core/java/android/metrics/OWNERS b/core/java/android/metrics/OWNERS
index ba867e0cad2b..98aaf3f47b21 100644
--- a/core/java/android/metrics/OWNERS
+++ b/core/java/android/metrics/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 26805
cwren@android.com
-cwren@google.com
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1e6469c57fa9..0ceafa01017e 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1515,7 +1515,7 @@ public class Build {
VERSION_CODES.VANILLA_ICE_CREAM * SDK_INT_MULTIPLIER;
/**
- * The upcoming, not yet finalized, version of Android.
+ * Android 36.0.
*/
public static final int BAKLAVA = VERSION_CODES.BAKLAVA * SDK_INT_MULTIPLIER;
}
diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
index 74972346bf2e..ce1717b60bfd 100644
--- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
@@ -92,11 +92,8 @@ public final class MessageQueue {
// queue for async messages when inserting a message at the tail.
private int mAsyncMessageCount;
- /**
- * @hide
- */
private final AtomicLong mMessageCount = new AtomicLong();
- private final Thread mThread;
+ private final String mThreadName;
private final long mTid;
/**
@@ -133,7 +130,7 @@ public final class MessageQueue {
mUseConcurrent = sIsProcessAllowedToUseConcurrent;
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
- mThread = Thread.currentThread();
+ mThreadName = Thread.currentThread().getName();
mTid = Process.myTid();
}
@@ -223,10 +220,10 @@ public final class MessageQueue {
traceMessageCount();
PerfettoTrace.instant(PerfettoTrace.MQ_CATEGORY, "message_queue_send")
- .addFlow(msg.mEventId.get())
+ .setFlow(msg.mEventId.get())
.beginProto()
.beginNested(2004 /* message_queue */)
- .addField(2 /* receiving_thread_name */, mThread.getName())
+ .addField(2 /* receiving_thread_name */, mThreadName)
.addField(3 /* message_code */, msg.what)
.addField(4 /* message_delay_ms */, when - SystemClock.uptimeMillis())
.endNested()
@@ -237,7 +234,7 @@ public final class MessageQueue {
/** @hide */
private void traceMessageCount() {
PerfettoTrace.counter(PerfettoTrace.MQ_CATEGORY, mMessageCount.get())
- .usingThreadCounterTrack(mTid, mThread.getName())
+ .usingThreadCounterTrack(mTid, mThreadName)
.emit();
}
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 8cfd32449537..48e6249d004a 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -451,7 +451,7 @@ public interface IBinder {
* @param executor The executor on which to run the callback.
* @param callback The callback used to deliver state change notifications.
*
- * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support
+ * @throws {@link UnsupportedOperationException} if the kernel binder driver does not support
* this feature.
*/
@FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK)
diff --git a/core/java/android/os/IpcDataCache.java b/core/java/android/os/IpcDataCache.java
index 240bc4f74820..2e7c3be53d90 100644
--- a/core/java/android/os/IpcDataCache.java
+++ b/core/java/android/os/IpcDataCache.java
@@ -719,9 +719,13 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query,
/**
* Enable or disable testing. The protocol requires that the mode toggle: for instance, it is
- * illegal to clear the test mode if the test mode is already off. The purpose is solely to
- * ensure that test clients do not forget to use the test mode properly, even though the
- * current logic does not care.
+ * illegal to clear the test mode if the test mode is already off. Enabling test mode puts
+ * all caches in the process into test mode; all nonces are initialized to UNSET and
+ * subsequent reads and writes are to process memory. This has the effect of disabling all
+ * caches that are not local to the process. Disabling test mode restores caches to normal
+ * operation.
+ * @param mode The desired test mode.
+ * @throws IllegalStateException if the supplied mode is already set.
* @hide
*/
@TestApi
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 1329b90538bb..3ff6e052335e 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -205,7 +205,7 @@ public final class Looper {
.addField(1 /* sending_thread_name */, msg.mSendingThreadName)
.endNested()
.endProto()
- .addTerminatingFlow(msg.mEventId.get())
+ .setTerminatingFlow(msg.mEventId.get())
.emit();
// This must be in a local variabe, in case a UI event sets the logger
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index b22d1774d967..69e84e3b097a 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -23,7 +23,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
/**
*
@@ -43,7 +43,7 @@ public final class Message implements Parcelable {
*
* @hide Only for use within the system server.
*/
- public final AtomicInteger mEventId = new AtomicInteger();
+ public final AtomicLong mEventId = new AtomicLong();
/**
* User-defined message code so that the recipient can identify
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 727dcbaca4bf..a6785bab56f3 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -78,7 +78,7 @@ per-file Trace.java = file:/TRACE_OWNERS
per-file PatternMatcher* = file:/PACKAGE_MANAGER_OWNERS
# PermissionEnforcer
-per-file PermissionEnforcer.java = tweek@google.com, brufino@google.com
+per-file PermissionEnforcer.java = tweek@google.com
# RemoteCallbackList
per-file RemoteCallbackList.java = shayba@google.com
diff --git a/core/java/android/os/PerfettoTrackEventExtra.java b/core/java/android/os/PerfettoTrackEventExtra.java
index f4b5dfe76f88..2848bcb8ad34 100644
--- a/core/java/android/os/PerfettoTrackEventExtra.java
+++ b/core/java/android/os/PerfettoTrackEventExtra.java
@@ -172,7 +172,6 @@ public final class PerfettoTrackEventExtra {
private final Pool<FieldDouble> mFieldDoubleCache;
private final Pool<FieldString> mFieldStringCache;
private final Pool<FieldNested> mFieldNestedCache;
- private final Pool<Flow> mFlowCache;
private final Pool<Builder> mBuilderCache;
private Builder() {
@@ -187,7 +186,6 @@ public final class PerfettoTrackEventExtra {
mFieldDoubleCache = mExtra.mFieldDoubleCache;
mFieldStringCache = mExtra.mFieldStringCache;
mFieldNestedCache = mExtra.mFieldNestedCache;
- mFlowCache = mExtra.mFlowCache;
mBuilderCache = mExtra.mBuilderCache;
mCounterInt64 = mExtra.getCounterInt64();
@@ -227,7 +225,6 @@ public final class PerfettoTrackEventExtra {
mFieldStringCache.reset();
mFieldNestedCache.reset();
mBuilderCache.reset();
- mFlowCache.reset();
mExtra.reset();
// Reset after on init in case the thread created builders without calling emit
@@ -325,39 +322,7 @@ public final class PerfettoTrackEventExtra {
/**
* Adds a flow with {@code id}.
*/
- public Builder addFlow(int id) {
- if (!mIsCategoryEnabled) {
- return this;
- }
- if (DEBUG) {
- checkParent();
- }
- Flow flow = mFlowCache.get(sFlowSupplier);
- flow.setProcessFlow(id);
- mExtra.addPerfettoPointer(flow);
- return this;
- }
-
- /**
- * Adds a terminating flow with {@code id}.
- */
- public Builder addTerminatingFlow(int id) {
- if (!mIsCategoryEnabled) {
- return this;
- }
- if (DEBUG) {
- checkParent();
- }
- Flow flow = mFlowCache.get(sFlowSupplier);
- flow.setProcessTerminatingFlow(id);
- mExtra.addPerfettoPointer(flow);
- return this;
- }
-
- /**
- * Adds a flow with {@code id}.
- */
- public Builder setFlow(int id) {
+ public Builder setFlow(long id) {
if (!mIsCategoryEnabled) {
return this;
}
@@ -372,7 +337,7 @@ public final class PerfettoTrackEventExtra {
/**
* Adds a terminating flow with {@code id}.
*/
- public Builder setTerminatingFlow(int id) {
+ public Builder setTerminatingFlow(long id) {
if (!mIsCategoryEnabled) {
return this;
}
@@ -670,7 +635,6 @@ public final class PerfettoTrackEventExtra {
private final Pool<FieldDouble> mFieldDoubleCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private final Pool<FieldString> mFieldStringCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private final Pool<FieldNested> mFieldNestedCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
- private final Pool<Flow> mFlowCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private final Pool<Builder> mBuilderCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
private static final NativeAllocationRegistry sRegistry =
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 77b6d70339ab..2736b60cd1f6 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -357,4 +357,9 @@ public abstract class PowerManagerInternal {
* This may affect dream eligibility.
*/
public abstract void setDevicePostured(boolean isPostured);
+
+ /**
+ * Notifies PowerManager that settings have changed and that it should refresh its state.
+ */
+ public abstract void updateSettings();
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 518820430419..561a2c96e6a7 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -16,6 +16,7 @@
package android.permission;
+import static android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -2039,12 +2040,49 @@ public final class PermissionManager {
new PackageNamePermissionQuery(permName, pkgName, persistentDeviceId, userId));
}
+ /**
+ * When checking a device-aware permission on a remote device, if the permission is CAMERA
+ * or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote
+ * device doesn't have capability fall back to checking permission on the default device.
+ *
+ * @hide
+ */
+ public static int resolveDeviceIdForPermissionCheck(@NonNull Context context, int deviceId,
+ @Nullable String permission) {
+ if (deviceId == Context.DEVICE_ID_DEFAULT || !DEVICE_AWARE_PERMISSIONS.contains(
+ permission)) {
+ return Context.DEVICE_ID_DEFAULT;
+ }
+
+ VirtualDeviceManager virtualDeviceManager =
+ context.getSystemService(VirtualDeviceManager.class);
+ if (virtualDeviceManager == null) {
+ Slog.e(LOG_TAG, "VDM is not enabled when device id is not default. deviceId = "
+ + deviceId);
+ } else {
+ VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
+ if (virtualDevice != null) {
+ if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO)
+ && !virtualDevice.hasCustomAudioInputSupport())
+ || (Objects.equals(permission, Manifest.permission.CAMERA)
+ && !virtualDevice.hasCustomCameraSupport())) {
+ deviceId = Context.DEVICE_ID_DEFAULT;
+ }
+ } else {
+ Slog.e(LOG_TAG,
+ "virtualDevice is not found when device id is not default. deviceId = "
+ + deviceId);
+ }
+ }
+ return deviceId;
+ }
+
@Nullable
private String getPersistentDeviceId(int deviceId) {
String persistentDeviceId = null;
if (deviceId == Context.DEVICE_ID_DEFAULT) {
- persistentDeviceId = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
+ persistentDeviceId = PERSISTENT_DEVICE_ID_DEFAULT;
} else {
VirtualDeviceManager virtualDeviceManager = mContext.getSystemService(
VirtualDeviceManager.class);
diff --git a/core/java/android/preference/OWNERS b/core/java/android/preference/OWNERS
index b4cb9ec7ceda..38a5abd8ff56 100644
--- a/core/java/android/preference/OWNERS
+++ b/core/java/android/preference/OWNERS
@@ -1,5 +1,4 @@
lpf@google.com
-pavlis@google.com
clarabayarri@google.com
-per-file SeekBarVolumizer.java = jmtrivi@google.com \ No newline at end of file
+per-file SeekBarVolumizer.java = jmtrivi@google.com
diff --git a/core/java/android/print/OWNERS b/core/java/android/print/OWNERS
index ce79f5d0c669..15f640650868 100644
--- a/core/java/android/print/OWNERS
+++ b/core/java/android/print/OWNERS
@@ -1,5 +1,4 @@
# Bug component: 47273
anothermark@google.com
-kumarashishg@google.com
bmgordon@google.com
diff --git a/core/java/android/printservice/OWNERS b/core/java/android/printservice/OWNERS
index ce79f5d0c669..15f640650868 100644
--- a/core/java/android/printservice/OWNERS
+++ b/core/java/android/printservice/OWNERS
@@ -1,5 +1,4 @@
# Bug component: 47273
anothermark@google.com
-kumarashishg@google.com
bmgordon@google.com
diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
index ea01fc98eda0..770e234381c4 100644
--- a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
+++ b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
@@ -16,7 +16,6 @@
package android.security.advancedprotection;
-import static android.app.admin.DevicePolicyIdentifiers.MEMORY_TAGGING_POLICY;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.UserManager.DISALLOW_CELLULAR_2G;
import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY;
@@ -59,6 +58,10 @@ import java.util.concurrent.Executor;
public final class AdvancedProtectionManager {
private static final String TAG = "AdvancedProtectionMgr";
+ //TODO(b/378931989): Switch to android.app.admin.DevicePolicyIdentifiers.MEMORY_TAGGING_POLICY
+ //when the appropriate flag is launched.
+ private static final String MEMORY_TAGGING_POLICY = "memoryTagging";
+
/**
* Advanced Protection's identifier for setting policies or restrictions in
* {@link DevicePolicyManager}.
@@ -359,8 +362,7 @@ public final class AdvancedProtectionManager {
featureId = FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES;
} else if (DISALLOW_CELLULAR_2G.equals(identifier)) {
featureId = FEATURE_ID_DISALLOW_CELLULAR_2G;
- } else if (android.app.admin.flags.Flags.setMtePolicyCoexistence() && MEMORY_TAGGING_POLICY
- .equals(identifier)) {
+ } else if (MEMORY_TAGGING_POLICY.equals(identifier)) {
featureId = FEATURE_ID_ENABLE_MTE;
} else {
throw new UnsupportedOperationException("Unsupported identifier: " + identifier);
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 3ca9d937b0ca..fdacd600b9f5 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -59,4 +59,6 @@ interface IDreamManager {
float screenBrightnessFloat, int screenBrightnessInt,
boolean useNormalBrightnessForDoze);
oneway void finishSelfOneway(in IBinder token, boolean immediate);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
+ void setScreensaverEnabled(boolean enabled);
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 41a64e22e058..744cdf6629e7 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1323,14 +1323,13 @@ public abstract class WallpaperService extends Service {
redrawNeeded ? 1 : 0));
return;
}
-
- final int transformHint = SurfaceControl.rotationToBufferTransform(
- (mDisplay.getInstallOrientation() + mDisplay.getRotation()) % 4);
- mSurfaceControl.setTransformHint(transformHint);
WindowLayout.computeSurfaceSize(mLayout, maxBounds, mWidth, mHeight,
mWinFrames.frame, false /* dragResizing */, mSurfaceSize);
if (mSurfaceControl.isValid()) {
+ final int transformHint = SurfaceControl.rotationToBufferTransform(
+ (mDisplay.getInstallOrientation() + mDisplay.getRotation()) % 4);
+ mSurfaceControl.setTransformHint(transformHint);
if (mBbqSurfaceControl == null) {
mBbqSurfaceControl = new SurfaceControl.Builder()
.setName("Wallpaper BBQ wrapper")
diff --git a/core/java/android/text/OWNERS b/core/java/android/text/OWNERS
index 0935ffd9dd81..b493ef7009d9 100644
--- a/core/java/android/text/OWNERS
+++ b/core/java/android/text/OWNERS
@@ -4,7 +4,6 @@ grantapher@google.com
halilibo@google.com
haoyuchang@google.com
justinghan@google.com
-klippenstein@google.com
nona@google.com
seanmcq@google.com
siyamed@google.com
diff --git a/core/java/android/util/apk/OWNERS b/core/java/android/util/apk/OWNERS
index 0f4e869f8b9a..f267f9a4edb6 100644
--- a/core/java/android/util/apk/OWNERS
+++ b/core/java/android/util/apk/OWNERS
@@ -1,3 +1,2 @@
include /core/java/android/content/pm/OWNERS
-cbrubaker@google.com
mpgroover@google.com
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 80484a6328e0..3353923292e1 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -3,7 +3,6 @@
romainguy@google.com
adamp@google.com
aurimas@google.com
-nduca@google.com
sumir@google.com
ogunwale@google.com
jjaggi@google.com
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index b98f4db5dce6..4f6c730857a8 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -2247,6 +2247,27 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
t.reparent(sc, mBlastSurfaceControl).show(sc);
}
+ /**
+ * Populates a {@link ViewStructure} for content capture.
+ *
+ * <p>If {@link #setSecure(boolean)} has been enabled, will add a property to the
+ * {@link android.app.assist.AssistStructure.ViewNode} to indicate that content will not
+ * be available for this part of the screen.
+ *
+ * @hide
+ */
+ @Override
+ protected void onProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, int flags) {
+ super.onProvideStructure(structure, viewFor, flags);
+ if (android.app.contextualsearch.flags.Flags.reportSecureSurfacesInAssistStructure()) {
+ if ((mSurfaceFlags & SurfaceControl.SECURE) != 0) {
+ structure.getExtras().putBoolean(
+ ViewStructure.EXTRA_CONTAINS_SECURE_LAYERS, true);
+ }
+ }
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c048d7987515..f50d77e6aead 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -34463,7 +34463,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@FlaggedApi(android.app.jank.Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
public void reportAppJankStats(@NonNull AppJankStats appJankStats) {
- getRootView().reportAppJankStats(appJankStats);
+ View rootView = getRootView();
+ if (rootView == this) return;
+
+ rootView.reportAppJankStats(appJankStats);
}
/**
@@ -34471,6 +34474,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public @Nullable JankTracker getJankTracker() {
- return getRootView().getJankTracker();
+ View rootView = getRootView();
+ if (rootView == this) {
+ return null;
+ }
+ return rootView.getJankTracker();
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7fd7be8585a4..e157da72196a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -153,6 +153,7 @@ import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
+import android.app.UiModeManager;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.app.servertransaction.WindowStateTransactionItem;
@@ -196,6 +197,7 @@ import android.hardware.display.DisplayManagerGlobal;
import android.hardware.input.InputManagerGlobal;
import android.hardware.input.InputSettings;
import android.media.AudioManager;
+import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -472,8 +474,6 @@ public final class ViewRootImpl implements ViewParent,
@Nullable
private ContentObserver mForceInvertObserver;
- private static final int INVALID_VALUE = Integer.MIN_VALUE;
- private int mForceInvertEnabled = INVALID_VALUE;
/**
* Callback for notifying about global configuration changes.
*/
@@ -555,6 +555,8 @@ public final class ViewRootImpl implements ViewParent,
@UiContext
public final Context mContext;
+ private UiModeManager mUiModeManager;
+
@UnsupportedAppUsage
final IWindowSession mWindowSession;
@NonNull Display mDisplay;
@@ -1804,23 +1806,6 @@ public final class ViewRootImpl implements ViewParent,
}
}
- private boolean isForceInvertEnabled() {
- if (mForceInvertEnabled == INVALID_VALUE) {
- reloadForceInvertEnabled();
- }
- return mForceInvertEnabled == 1;
- }
-
- private void reloadForceInvertEnabled() {
- if (forceInvertColor()) {
- mForceInvertEnabled = Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
- /* def= */ 0,
- UserHandle.myUserId());
- }
- }
-
/**
* Register any kind of listeners if setView was success.
*/
@@ -1856,17 +1841,22 @@ public final class ViewRootImpl implements ViewParent,
mForceInvertObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
- reloadForceInvertEnabled();
updateForceDarkMode();
}
};
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED
- ),
- false,
- mForceInvertObserver,
- UserHandle.myUserId());
+
+ final Uri[] urisToObserve = {
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED),
+ Settings.Secure.getUriFor(Settings.Secure.UI_NIGHT_MODE)
+ };
+ for (Uri uri : urisToObserve) {
+ mContext.getContentResolver().registerContentObserver(
+ uri,
+ false,
+ mForceInvertObserver,
+ UserHandle.myUserId());
+ }
}
}
}
@@ -2073,21 +2063,25 @@ public final class ViewRootImpl implements ViewParent,
return getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
}
- /** Returns true if force dark should be enabled according to various settings */
+ /**
+ * Determines the type of force dark to apply, considering force inversion, system night mode,
+ * and app-specific settings (including developer opt-outs).
+ *
+ * @return A {@link ForceDarkType.ForceDarkTypeDef} constant indicating the force dark type.
+ */
@VisibleForTesting
public @ForceDarkType.ForceDarkTypeDef int determineForceDarkType() {
if (forceInvertColor()) {
// Force invert ignores all developer opt-outs.
// We also ignore dark theme, since the app developer can override the user's preference
- // for dark mode in configuration.uiMode. Instead, we assume that the force invert
- // setting will be enabled at the same time dark theme is in the Settings app.
- if (isForceInvertEnabled()) {
+ // for dark mode in configuration.uiMode. Instead, we assume that both force invert and
+ // the system's dark theme are enabled.
+ if (getUiModeManager().getForceInvertState() == UiModeManager.FORCE_INVERT_TYPE_DARK) {
return ForceDarkType.FORCE_INVERT_COLOR_DARK;
}
}
boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
-
if (useAutoDark) {
boolean forceDarkAllowedDefault =
SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false);
@@ -9401,6 +9395,13 @@ public final class ViewRootImpl implements ViewParent,
return mAudioManager;
}
+ private UiModeManager getUiModeManager() {
+ if (mUiModeManager == null) {
+ mUiModeManager = mContext.getSystemService(UiModeManager.class);
+ }
+ return mUiModeManager;
+ }
+
private Vibrator getSystemVibrator() {
if (mVibrator == null) {
mVibrator = mContext.getSystemService(Vibrator.class);
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 43a946a234ba..53953a9379df 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -77,6 +77,19 @@ public abstract class ViewStructure {
"android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION";
/**
+ * Key used for confirming whether the view draws graphics containing secure layers.
+ *
+ * <p>Secure layers cannot be read back into main memory and will show up as blank regions
+ * in assist screenshots.
+ *
+ * @see android.view.SurfaceControl#SECURE
+ *
+ * @hide
+ */
+ public static final String EXTRA_CONTAINS_SECURE_LAYERS =
+ "android.view.ViewStructure.extra.CONTAINS_SECURE_LAYERS";
+
+ /**
* Key used for writing the type of the view that generated the virtual structure of its
* children.
*
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 196ae5e59fa7..83dc79beb75e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -631,6 +631,12 @@ public interface WindowManager extends ViewManager {
int TRANSIT_FLAG_AOD_APPEARING = (1 << 15); // 0x8000
/**
+ * Transition flag: Indicates that the task shouldn't move to front when launching the activity.
+ * @hide
+ */
+ int TRANSIT_FLAG_AVOID_MOVE_TO_FRONT = (1 << 16); // 0x10000
+
+ /**
* @hide
*/
@IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
@@ -650,6 +656,7 @@ public interface WindowManager extends ViewManager {
TRANSIT_FLAG_KEYGUARD_UNOCCLUDING,
TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH,
TRANSIT_FLAG_AOD_APPEARING,
+ TRANSIT_FLAG_AVOID_MOVE_TO_FRONT,
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitionFlags {}
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
index 705f4b342d42..f3450344ea81 100644
--- a/core/java/android/view/inspector/OWNERS
+++ b/core/java/android/view/inspector/OWNERS
@@ -2,5 +2,4 @@ romainguy@google.com
alanv@google.com
adamp@google.com
aurimas@google.com
-nduca@google.com
sumir@google.com
diff --git a/core/java/android/webkit/TEST_MAPPING b/core/java/android/webkit/TEST_MAPPING
index 38580595dc2d..c9b54760491a 100644
--- a/core/java/android/webkit/TEST_MAPPING
+++ b/core/java/android/webkit/TEST_MAPPING
@@ -17,15 +17,6 @@
"exclude-annotation": "android.test.FlakyTest"
}
]
- },
- {
- "name": "GtsWebViewHostTestCases",
- "keywords": ["internal"],
- "options": [
- {
- "exclude-annotation": "android.test.FlakyTest"
- }
- ]
}
]
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 14b208aecf5c..ab7a4f289d73 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1458,13 +1458,14 @@ public abstract class WebSettings {
public abstract void setNeedInitialFocus(boolean flag);
/**
- * Sets the priority of the Render thread. Unlike the other settings, this
+ * Sets the CPU scheduling priority of the Render thread. Unlike the other settings, this
* one only needs to be called once per process. The default value is
* {@link RenderPriority#NORMAL}.
*
* @param priority the priority
- * @deprecated It is not recommended to adjust thread priorities, and this will
- * not be supported in future versions.
+ * @deprecated This is no longer supported. See {@link WebView#setRendererPriorityPolicy} if you
+ * instead want to control how freely the system should kill the renderer process
+ * under low memory conditions.
*/
@Deprecated
public abstract void setRenderPriority(RenderPriority priority);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index b6663992b851..5e22c287140a 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2287,26 +2287,53 @@ public class WebView extends AbsoluteLayout
public @interface RendererPriority {}
/**
- * The renderer associated with this WebView is bound with
- * {@link Context#BIND_WAIVE_PRIORITY}. At this priority level
- * {@link WebView} renderers will be strong targets for out of memory
- * killing.
+ * This is the lowest binding priority for the WebView renderer process. This is equivalent to
+ * {@link Context#BIND_WAIVE_PRIORITY}. At this priority level {@link WebView} renderers will be
+ * frequent targets for being killed when the system is running low on memory.
+ *
+ * <p>If using this priority, we recommend handling the {@link
+ * WebViewClient#onRenderProcessGone} callback to recover from low memory kills as well as other
+ * types of renderer crashes.
*
- * Use with {@link #setRendererPriorityPolicy}.
+ * @see #setRendererPriorityPolicy
+ * @see #getRendererPriorityPolicy
+ * @see RenderProcessGoneDetail#rendererPriorityAtExit
*/
public static final int RENDERER_PRIORITY_WAIVED = 0;
+
/**
- * The renderer associated with this WebView is bound with
- * the default priority for services.
+ * This is the medium binding priority for the WebView renderer process. This is equivalent to
+ * the standard priority used by the system for calls to {@link
+ * Context#bindService(Intent,android.content.ServiceConnection,int)} when no flags are
+ * provided. At this priority level {@link WebView} renderers will be slightly more likely
+ * targets for being killed when the system is running low on memory.
*
- * Use with {@link #setRendererPriorityPolicy}.
+ * <p>If using this priority, we recommend handling the {@link
+ * WebViewClient#onRenderProcessGone} callback to recover from low memory kills as well as other
+ * types of renderer crashes.
+ *
+ * @see #setRendererPriorityPolicy
+ * @see #getRendererPriorityPolicy
+ * @see RenderProcessGoneDetail#rendererPriorityAtExit
*/
public static final int RENDERER_PRIORITY_BOUND = 1;
+
/**
- * The renderer associated with this WebView is bound with
- * {@link Context#BIND_IMPORTANT}.
+ * This is the highest binding priority for the WebView renderer process, and the default value
+ * WebView uses to bind to the renderer process. This is equivalent to {@link
+ * Context#BIND_IMPORTANT}. At this priority level {@link WebView} renderers are less likely to
+ * be killed when the system is running low on memory and will have the same priority as your
+ * app's main process.
+ *
+ * <p>It's still possible for the renderer process to be killed when the system is running low
+ * on memory, however specifying this priority makes this situation less likely. It's also still
+ * possible for the renderer process to crash for other reasons. You may optionally still choose
+ * to handle {@link WebViewClient#onRenderProcessGone} in order to recover from a killed or
+ * crashed renderer process.
*
- * Use with {@link #setRendererPriorityPolicy}.
+ * @see #setRendererPriorityPolicy
+ * @see #getRendererPriorityPolicy
+ * @see RenderProcessGoneDetail#rendererPriorityAtExit
*/
public static final int RENDERER_PRIORITY_IMPORTANT = 2;
@@ -2316,7 +2343,7 @@ public class WebView extends AbsoluteLayout
* process renderer should be considered to be a target for OOM
* killing.
*
- * Because a renderer can be associated with more than one
+ * <p>Because a renderer can be associated with more than one
* WebView, the final priority it is computed as the maximum of
* any attached WebViews. When a WebView is destroyed it will
* cease to be considerered when calculating the renderer
@@ -2324,7 +2351,7 @@ public class WebView extends AbsoluteLayout
* the priority of the renderer will be reduced to
* {@link #RENDERER_PRIORITY_WAIVED}.
*
- * The default policy is to set the priority to
+ * <p>The default policy is to set the priority to
* {@link #RENDERER_PRIORITY_IMPORTANT} regardless of visibility,
* and this should not be changed unless the caller also handles
* renderer crashes with
@@ -2338,6 +2365,8 @@ public class WebView extends AbsoluteLayout
* when this WebView is not visible, it will be treated as
* if it had requested a priority of
* {@link #RENDERER_PRIORITY_WAIVED}.
+ * @see #getRendererPriorityPolicy
+ * @see RenderProcessGoneDetail#rendererPriorityAtExit
*/
public void setRendererPriorityPolicy(
@RendererPriority int rendererRequestedPriority,
@@ -2349,6 +2378,8 @@ public class WebView extends AbsoluteLayout
* Get the requested renderer priority for this WebView.
*
* @return the requested renderer priority policy.
+ * @see #setRendererPriorityPolicy
+ * @see RenderProcessGoneDetail#rendererPriorityAtExit
*/
@InspectableProperty(hasAttributeId = false, enumMapping = {
@InspectableProperty.EnumEntry(name = "waived", value = RENDERER_PRIORITY_WAIVED),
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index e74a87536c57..696b7b8bb965 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -61,6 +61,8 @@ public enum DesktopModeFlags {
ENABLE_DESKTOP_COMPAT_UI_VISIBILITY_STATUS(Flags::enableCompatUiVisibilityStatus, true),
ENABLE_DESKTOP_INDICATOR_IN_SEPARATE_THREAD_BUGFIX(
Flags::enableDesktopIndicatorInSeparateThreadBugfix, false),
+ ENABLE_DESKTOP_OPENING_DEEPLINK_MINIMIZE_ANIMATION_BUGFIX(
+ Flags::enableDesktopOpeningDeeplinkMinimizeAnimationBugfix, false),
ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX(
Flags::enableDesktopRecentsTransitionsCornersBugfix, false),
ENABLE_DESKTOP_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE_BUGFIX(
@@ -112,6 +114,8 @@ public enum DesktopModeFlags {
ENABLE_RESIZING_METRICS(Flags::enableResizingMetrics, true),
ENABLE_RESTORE_TO_PREVIOUS_SIZE_FROM_DESKTOP_IMMERSIVE(
Flags::enableRestoreToPreviousSizeFromDesktopImmersive, true),
+ ENABLE_SHELL_INITIAL_BOUNDS_REGRESSION_BUG_FIX(
+ Flags::enableShellInitialBoundsRegressionBugFix, false),
ENABLE_START_LAUNCH_TRANSITION_FROM_TASKBAR_BUGFIX(
Flags::enableStartLaunchTransitionFromTaskbarBugfix, true),
ENABLE_TASKBAR_OVERFLOW(Flags::enableTaskbarOverflow, false),
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 63c55ad6a889..be4edc3b6ec5 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -29,6 +29,7 @@ import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_NONE;
@@ -375,7 +376,8 @@ public final class TransitionInfo implements Parcelable {
*/
public boolean hasChangesOrSideEffects() {
return !mChanges.isEmpty() || isKeyguardGoingAway()
- || (mFlags & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0;
+ || (mFlags & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0
+ || (mFlags & TRANSIT_FLAG_AOD_APPEARING) != 0;
}
/**
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 355a87d72203..09f458be9bfa 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -38,6 +38,18 @@ flag {
}
flag {
+ name: "enable_shell_initial_bounds_regression_bug_fix"
+ namespace: "lse_desktop_experience"
+ description: "Enables fix for Shell initial bounds regression, forcing core to calculate /n"
+ "initial bounds in desktop launch params while respecting cascading position /n"
+ "passed by Shell."
+ bug: "396075922"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "enable_windowing_dynamic_initial_bounds"
namespace: "lse_desktop_experience"
description: "Enables new initial bounds for desktop windowing which adjust depending on app constraints"
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 9f768f065fe9..f2efa200918c 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -152,4 +152,15 @@ flag {
metadata {
purpose: PURPOSE_BUGFIX
}
-} \ No newline at end of file
+}
+
+flag {
+ namespace: "windowing_sdk"
+ name: "cleanup_dispatch_pending_transactions_remote_exception"
+ description: "Refactor to cleanup for RemoteException from dispatchPendingTransactions"
+ bug: "323801078"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/com/android/internal/config/appcloning/OWNERS b/core/java/com/android/internal/config/appcloning/OWNERS
index 0645a8c54414..9369438deb07 100644
--- a/core/java/com/android/internal/config/appcloning/OWNERS
+++ b/core/java/com/android/internal/config/appcloning/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 1207885
jigarthakkar@google.com
-saumyap@google.com \ No newline at end of file
diff --git a/core/java/com/android/internal/infra/OWNERS b/core/java/com/android/internal/infra/OWNERS
index 45503582b2c5..e69de29bb2d1 100644
--- a/core/java/com/android/internal/infra/OWNERS
+++ b/core/java/com/android/internal/infra/OWNERS
@@ -1,6 +0,0 @@
-per-file AndroidFuture.java = eugenesusla@google.com
-per-file RemoteStream.java = eugenesusla@google.com
-per-file PerUser.java = eugenesusla@google.com
-per-file ServiceConnector.java = eugenesusla@google.com
-per-file AndroidFuture.aidl = eugenesusla@google.com
-per-file IAndroidFuture.aidl = eugenesusla@google.com \ No newline at end of file
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 056a0e85ae97..81ca23173457 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -789,7 +789,7 @@ public class BatteryStatsHistory {
*/
public boolean readFragmentToParcel(Parcel out, BatteryHistoryFragment fragment) {
byte[] data = mStore.readFragment(fragment);
- if (data == null) {
+ if (data == null || data.length == 0) {
return false;
}
out.unmarshall(data, 0, data.length);
@@ -934,6 +934,10 @@ public class BatteryStatsHistory {
continue;
}
+ if (data.length == 0) {
+ continue;
+ }
+
out.writeBoolean(true);
if (useBlobs) {
out.writeBlob(data, 0, data.length);
@@ -976,9 +980,11 @@ public class BatteryStatsHistory {
return false;
}
- parcel.unmarshall(data, 0, data.length);
- parcel.setDataPosition(0);
- readHistoryBuffer(parcel);
+ if (data.length > 0) {
+ parcel.unmarshall(data, 0, data.length);
+ parcel.setDataPosition(0);
+ readHistoryBuffer(parcel);
+ }
} catch (Exception e) {
Slog.e(TAG, "Error reading battery history", e);
reset();
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 9be8ea7aadc4..d174fe36e460 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -1,8 +1,8 @@
-per-file AsyncChannel* = lorenzo@google.com, satk@google.com, etancohen@google.com
+per-file AsyncChannel* = lorenzo@google.com, satk@google.com
per-file MessageUtils*, Protocol*, RingBuffer*, TokenBucket* = jchalard@google.com, lorenzo@google.com, satk@google.com
per-file *Notification* = file:/services/core/java/com/android/server/notification/OWNERS
per-file *ContrastColor* = file:/services/core/java/com/android/server/notification/OWNERS
-per-file Protocol* = etancohen@google.com, lorenzo@google.com
+per-file Protocol* =lorenzo@google.com
per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com
per-file *Dump* = file:/core/java/com/android/internal/util/dump/OWNERS
per-file *Screenshot* = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS
diff --git a/core/java/com/android/internal/util/function/pooled/OWNERS b/core/java/com/android/internal/util/function/pooled/OWNERS
index da723b3b67da..e69de29bb2d1 100644
--- a/core/java/com/android/internal/util/function/pooled/OWNERS
+++ b/core/java/com/android/internal/util/function/pooled/OWNERS
@@ -1 +0,0 @@
-eugenesusla@google.com \ No newline at end of file
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 453a0755ec5b..2cca3dbc4f2f 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -86,6 +86,7 @@ public class ConversationLayout extends FrameLayout
public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
public static final Interpolator OVERSHOOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
+ private static final int MAX_SUMMARIZATION_LINES = 3;
public static final int IMPORTANCE_ANIM_GROW_DURATION = 250;
public static final int IMPORTANCE_ANIM_SHRINK_DURATION = 200;
public static final int IMPORTANCE_ANIM_SHRINK_DELAY = 25;
@@ -401,7 +402,7 @@ public class ConversationLayout extends FrameLayout
public void setIsCollapsed(boolean isCollapsed) {
mIsCollapsed = isCollapsed;
mMessagingLinearLayout.setMaxDisplayedLines(isCollapsed
- ? TextUtils.isEmpty(mSummarizedContent) ? 1 : 2
+ ? TextUtils.isEmpty(mSummarizedContent) ? 1 : MAX_SUMMARIZATION_LINES
: Integer.MAX_VALUE);
updateExpandButton();
updateContentEndPaddings();
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index f2099bc76109..9fe2de82adee 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -63,6 +63,7 @@ public class MessagingLayout extends FrameLayout
public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
+ private static final int MAX_SUMMARIZATION_LINES = 3;
public static final OnLayoutChangeListener MESSAGING_PROPERTY_ANIMATOR
= new MessagingPropertyAnimator();
private final PeopleHelper mPeopleHelper = new PeopleHelper();
@@ -223,7 +224,7 @@ public class MessagingLayout extends FrameLayout
List<MessagingMessage> newMessagingMessages;
mSummarizedContent = extras.getCharSequence(Notification.EXTRA_SUMMARIZED_CONTENT);
if (!TextUtils.isEmpty(mSummarizedContent) && mIsCollapsed) {
- mMessagingLinearLayout.setMaxDisplayedLines(2);
+ mMessagingLinearLayout.setMaxDisplayedLines(MAX_SUMMARIZATION_LINES);
Notification.MessagingStyle.Message summary =
new Notification.MessagingStyle.Message(mSummarizedContent, 0, "");
newMessagingMessages = createMessages(List.of(summary), false, usePrecomputedText);
diff --git a/core/java/com/android/internal/widget/remotecompose/OWNERS b/core/java/com/android/internal/widget/remotecompose/OWNERS
index e163474bccb9..c606744df150 100644
--- a/core/java/com/android/internal/widget/remotecompose/OWNERS
+++ b/core/java/com/android/internal/widget/remotecompose/OWNERS
@@ -1,6 +1,5 @@
nicolasroard@google.com
hoford@google.com
-jnichol@google.com
sihua@google.com
sunnygoyal@google.com
oscarad@google.com
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 92a841f9c290..748c5b48534f 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -21,7 +21,6 @@ soong_config_module_type {
config_namespace: "ANDROID",
bool_variables: [
"release_binder_death_recipient_weak_from_jni",
- "release_package_libandroid_runtime_punch_holes",
],
properties: [
"cflags",
@@ -66,9 +65,6 @@ cc_library_shared_for_libandroid_runtime {
release_binder_death_recipient_weak_from_jni: {
cflags: ["-DBINDER_DEATH_RECIPIENT_WEAK_FROM_JNI"],
},
- release_package_libandroid_runtime_punch_holes: {
- cflags: ["-DENABLE_PUNCH_HOLES"],
- },
},
cpp_std: "gnu++20",
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 06fd80e37669..14132e61ff0e 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -236,7 +236,6 @@ static install_status_t extractNativeLibFromApk(ZipFileRO* zipFile, ZipEntryRO z
return INSTALL_FAILED_CONTAINER_ERROR;
}
-#ifdef ENABLE_PUNCH_HOLES
// punch extracted elf files as well. This will fail where compression is on (like f2fs) but it
// will be useful for ext4 based systems
struct statfs64 fsInfo;
@@ -253,7 +252,6 @@ static install_status_t extractNativeLibFromApk(ZipFileRO* zipFile, ZipEntryRO z
zipFile->getZipFileName());
}
}
-#endif // ENABLE_PUNCH_HOLES
ALOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName);
@@ -332,7 +330,6 @@ static install_status_t copyFileIfChanged(JNIEnv* env, void* arg, ZipFileRO* zip
return INSTALL_FAILED_INVALID_APK;
}
-#ifdef ENABLE_PUNCH_HOLES
// if library is uncompressed, punch hole in it in place
if (!punchHolesInElf64(zipFile->getZipFileName(), offset)) {
ALOGW("Failed to punch uncompressed elf file :%s inside apk : %s at offset: "
@@ -345,7 +342,6 @@ static install_status_t copyFileIfChanged(JNIEnv* env, void* arg, ZipFileRO* zip
if (!punchHolesInZip(zipFile->getZipFileName(), offset, extraFieldLength)) {
ALOGW("Failed to punch apk : %s at extra field", zipFile->getZipFileName());
}
-#endif // ENABLE_PUNCH_HOLES
return INSTALL_SUCCEEDED;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ee6899cf866b..e16ce9849ff2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8995,13 +8995,13 @@
<!-- @SystemApi
@FlaggedApi("android.permission.flags.text_classifier_choice_api_enabled")
- This permission is required to access the specific text classifier you need from the
+ This permission is required to access the specific text classifier from the
TextClassificationManager.
- <p>Protection level: signature|role
+ <p>Protection level: signature|role|privileged
@hide
-->
<permission android:name="android.permission.ACCESS_TEXT_CLASSIFIER_BY_TYPE"
- android:protectionLevel="signature|role"
+ android:protectionLevel="signature|role|privileged"
android:featureFlag="android.permission.flags.text_classifier_choice_api_enabled"/>
<!-- Attribution for Geofencing service. -->
diff --git a/core/res/OWNERS b/core/res/OWNERS
index faed4d80f39b..a208f7f1a3ad 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -9,7 +9,6 @@ hackbod@google.com
ilyamaty@google.com
jbolinger@google.com
jsharkey@android.com
-jsharkey@google.com
juliacr@google.com
kchyn@google.com
michaelwr@google.com
diff --git a/core/res/res/layout/accessibility_autoclick_type_panel.xml b/core/res/res/layout/accessibility_autoclick_type_panel.xml
index cedbdc175488..902ef7fc38e8 100644
--- a/core/res/res/layout/accessibility_autoclick_type_panel.xml
+++ b/core/res/res/layout/accessibility_autoclick_type_panel.xml
@@ -17,7 +17,7 @@
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.server.accessibility.autoclick.AutoclickLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/accessibility_autoclick_type_panel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -130,4 +130,4 @@
</LinearLayout>
-</LinearLayout>
+</com.android.server.accessibility.autoclick.AutoclickLinearLayout>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index 77d2e873682f..0efa1bcbf975 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -163,15 +163,18 @@
<item>en-CM</item> <!-- English (Cameroon) -->
<item>en-CX</item> <!-- English (Christmas Island) -->
<item>en-CY</item> <!-- English (Cyprus) -->
+ <item>en-CZ</item> <!-- English (Czechia) -->
<item>en-DE</item> <!-- English (Germany) -->
<item>en-DG</item> <!-- English (Diego Garcia) -->
<item>en-DK</item> <!-- English (Denmark) -->
<item>en-DM</item> <!-- English (Dominica) -->
<item>en-ER</item> <!-- English (Eritrea) -->
+ <item>en-ES</item> <!-- English (Spain) -->
<item>en-FI</item> <!-- English (Finland) -->
<item>en-FJ</item> <!-- English (Fiji) -->
<item>en-FK</item> <!-- English (Falkland Islands (Islas Malvinas)) -->
<item>en-FM</item> <!-- English (Micronesia) -->
+ <item>en-FR</item> <!-- English (France) -->
<item>en-GB</item> <!-- English (United Kingdom) -->
<item>en-GD</item> <!-- English (Grenada) -->
<item>en-GG</item> <!-- English (Guernsey) -->
@@ -181,12 +184,14 @@
<item>en-GU</item> <!-- English (Guam) -->
<item>en-GY</item> <!-- English (Guyana) -->
<item>en-HK</item> <!-- English (Hong Kong) -->
+ <item>en-HU</item> <!-- English (Hungary) -->
<item>en-ID</item> <!-- English (Indonesia) -->
<item>en-IE</item> <!-- English (Ireland) -->
<item>en-IL</item> <!-- English (Israel) -->
<item>en-IM</item> <!-- English (Isle of Man) -->
<item>en-IN</item> <!-- English (India) -->
<item>en-IO</item> <!-- English (British Indian Ocean Territory) -->
+ <item>en-IT</item> <!-- English (Italy) -->
<item>en-JE</item> <!-- English (Jersey) -->
<item>en-JM</item> <!-- English (Jamaica) -->
<item>en-KE</item> <!-- English (Kenya) -->
@@ -210,15 +215,19 @@
<item>en-NF</item> <!-- English (Norfolk Island) -->
<item>en-NG</item> <!-- English (Nigeria) -->
<item>en-NL</item> <!-- English (Netherlands) -->
+ <item>en-NO</item> <!-- English (Norway) -->
<item>en-NR</item> <!-- English (Nauru) -->
<item>en-NU</item> <!-- English (Niue) -->
<item>en-NZ</item> <!-- English (New Zealand) -->
<item>en-PG</item> <!-- English (Papua New Guinea) -->
<item>en-PH</item> <!-- English (Philippines) -->
<item>en-PK</item> <!-- English (Pakistan) -->
+ <item>en-PL</item> <!-- English (Poland) -->
<item>en-PN</item> <!-- English (Pitcairn Islands) -->
<item>en-PR</item> <!-- English (Puerto Rico) -->
+ <item>en-PT</item> <!-- English (Portugal) -->
<item>en-PW</item> <!-- English (Palau) -->
+ <item>en-RO</item> <!-- English (Romania) -->
<item>en-RW</item> <!-- English (Rwanda) -->
<item>en-SB</item> <!-- English (Solomon Islands) -->
<item>en-SC</item> <!-- English (Seychelles) -->
@@ -227,6 +236,7 @@
<item>en-SG</item> <!-- English (Singapore) -->
<item>en-SH</item> <!-- English (St. Helena) -->
<item>en-SI</item> <!-- English (Slovenia) -->
+ <item>en-SK</item> <!-- English (Slovakia) -->
<item>en-SL</item> <!-- English (Sierra Leone) -->
<item>en-SS</item> <!-- English (South Sudan) -->
<item>en-SX</item> <!-- English (Sint Maarten) -->
diff --git a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
index ac78e87aa60d..f75a72d635dd 100644
--- a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
+++ b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
@@ -414,16 +414,23 @@ public class PropertyInvalidatedCacheTests {
@Test
@DisabledOnRavenwood(reason = "SystemProperties doesn't have permission check")
public void testPermissionFailure() {
- // Create a cache that will write a system nonce.
- TestCache sysCache = new TestCache(MODULE_SYSTEM, "mode1");
try {
- // Invalidate the cache, which writes the system property. There must be a permission
- // failure.
- sysCache.invalidateCache();
- fail("expected permission failure");
- } catch (RuntimeException e) {
- // The expected exception is a bare RuntimeException. The test does not attempt to
- // validate the text of the exception message.
+ // Disable the test mode for this test, but ensure that it will be enabled when the
+ // test exits.
+ PropertyInvalidatedCache.setTestMode(false);
+ // Create a cache that will write a system nonce.
+ TestCache sysCache = new TestCache(MODULE_SYSTEM, "mode1");
+ try {
+ // Invalidate the cache, which writes the system property. There must be a
+ // permission failure.
+ sysCache.invalidateCache();
+ fail("expected permission failure");
+ } catch (RuntimeException e) {
+ // The expected exception is a bare RuntimeException. The test does not attempt
+ // to validate the text of the exception message.
+ }
+ } finally {
+ PropertyInvalidatedCache.setTestMode(true);
}
}
diff --git a/core/tests/coretests/src/android/content/pm/OWNERS b/core/tests/coretests/src/android/content/pm/OWNERS
index 867336515ce3..c4c40dcaa87a 100644
--- a/core/tests/coretests/src/android/content/pm/OWNERS
+++ b/core/tests/coretests/src/android/content/pm/OWNERS
@@ -1,5 +1,4 @@
include /core/java/android/content/pm/OWNERS
per-file AppSearchPersonTest.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS
-per-file SigningDetailsTest.java = cbrubaker@google.com
per-file SigningDetailsTest.java = mpgroover@google.com
diff --git a/core/tests/coretests/src/android/os/IpcDataCacheTest.java b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
index 74b32a17d964..791ec5d0cea3 100644
--- a/core/tests/coretests/src/android/os/IpcDataCacheTest.java
+++ b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
@@ -452,22 +452,28 @@ public class IpcDataCacheTest {
assertTrue(ec.isDisabled());
}
-
// Verify that invalidating the cache from an app process would fail due to lack of permissions.
@Test
@android.platform.test.annotations.DisabledOnRavenwood(
reason = "SystemProperties doesn't have permission check")
public void testPermissionFailure() {
- // Create a cache that will write a system nonce.
- TestCache sysCache = new TestCache(IpcDataCache.MODULE_SYSTEM, "mode1");
try {
- // Invalidate the cache, which writes the system property. There must be a permission
- // failure.
- sysCache.invalidateCache();
- fail("expected permission failure");
- } catch (RuntimeException e) {
- // The expected exception is a bare RuntimeException. The test does not attempt to
- // validate the text of the exception message.
+ // Disable test mode for this test. Guarantee that the mode is enabled before the
+ // test exits.
+ IpcDataCache.setTestMode(false);
+ // Create a cache that will write a system nonce.
+ TestCache sysCache = new TestCache(IpcDataCache.MODULE_SYSTEM, "mode1");
+ try {
+ // Invalidate the cache, which writes the system property. There must be a
+ // permission failure.
+ sysCache.invalidateCache();
+ fail("expected permission failure");
+ } catch (RuntimeException e) {
+ // The expected exception is a bare RuntimeException. The test does not attempt
+ // to validate the text of the exception message.
+ }
+ } finally {
+ IpcDataCache.setTestMode(true);
}
}
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index f5d1e7a85e83..39f3d3319ad3 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.app.UiModeManager.MODE_NIGHT_NO;
+import static android.app.UiModeManager.MODE_NIGHT_YES;
import static android.util.SequenceUtils.getInitSeq;
import static android.view.HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING;
import static android.view.InputDevice.SOURCE_ROTARY_ENCODER;
@@ -67,8 +69,10 @@ import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
import android.app.Instrumentation;
import android.app.UiModeManager;
+import android.app.UiModeManager.ForceInvertType;
import android.content.Context;
import android.graphics.ForceDarkType;
+import android.graphics.ForceDarkType.ForceDarkTypeDef;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Binder;
@@ -93,9 +97,12 @@ import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.compatibility.common.util.TestUtils;
import com.android.cts.input.BlockingQueueEventVerifier;
import com.android.window.flags.Flags;
+import com.google.common.truth.Expect;
+
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.AfterClass;
@@ -124,6 +131,8 @@ public class ViewRootImplTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Rule
+ public final Expect mExpect = Expect.create();
private ViewRootImpl mViewRootImpl;
private View mView;
@@ -1507,49 +1516,34 @@ public class ViewRootImplTest {
}
@Test
- public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() {
- mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
- ShellIdentityUtils.invokeWithShellPermissions(() -> {
- Settings.Secure.putInt(
- sContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
- /* value= */ 0
- );
- var uiModeManager = sContext.getSystemService(UiModeManager.class);
- uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
- });
-
- sInstrumentation.runOnMainSync(() ->
- mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
- );
-
- assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
- }
-
- @Test
- public void forceInvertOnDarkThemeOff_forceDarkModeEnabled() {
- mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
- ShellIdentityUtils.invokeWithShellPermissions(() -> {
- Settings.Secure.putInt(
- sContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
- /* value= */ 1
- );
- var uiModeManager = sContext.getSystemService(UiModeManager.class);
- uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
- });
-
- sInstrumentation.runOnMainSync(() ->
- mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
- );
-
- assertThat(mViewRootImpl.determineForceDarkType())
- .isEqualTo(ForceDarkType.FORCE_INVERT_COLOR_DARK);
+ @RequiresFlagsEnabled(FLAG_FORCE_INVERT_COLOR)
+ public void updateConfiguration_returnsExpectedForceDarkMode() {
+ waitForSystemNightModeActivated(true);
+
+ verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
+ UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
+ verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
+ UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+ verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
+ UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
+ verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
+ UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+
+ waitForSystemNightModeActivated(false);
+
+ verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
+ UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+ verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
+ UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+ verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
+ UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+ verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
+ UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
}
@Test
+ @EnableFlags(FLAG_FORCE_INVERT_COLOR)
public void forceInvertOffForceDarkOff_forceDarkModeDisabled() {
- mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
ShellIdentityUtils.invokeWithShellPermissions(() -> {
Settings.Secure.putInt(
sContext.getContentResolver(),
@@ -1562,15 +1556,14 @@ public class ViewRootImplTest {
});
sInstrumentation.runOnMainSync(() ->
- mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
- );
+ mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
}
@Test
+ @EnableFlags(FLAG_FORCE_INVERT_COLOR)
public void forceInvertOffForceDarkOn_forceDarkModeEnabled() {
- mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
ShellIdentityUtils.invokeWithShellPermissions(() -> {
Settings.Secure.putInt(
sContext.getContentResolver(),
@@ -1582,8 +1575,7 @@ public class ViewRootImplTest {
});
sInstrumentation.runOnMainSync(() ->
- mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
- );
+ mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.FORCE_DARK);
}
@@ -1790,4 +1782,39 @@ public class ViewRootImplTest {
() -> view.getViewTreeObserver().removeOnDrawListener(listener));
}
}
+
+ private void waitForSystemNightModeActivated(boolean active) {
+ ShellIdentityUtils.invokeWithShellPermissions(() ->
+ sInstrumentation.runOnMainSync(() -> {
+ var uiModeManager = sContext.getSystemService(UiModeManager.class);
+ uiModeManager.setNightModeActivated(active);
+ }));
+ sInstrumentation.waitForIdleSync();
+ }
+
+ private void verifyForceDarkType(boolean isAppInNightMode, boolean isForceInvertEnabled,
+ @ForceInvertType int expectedForceInvertType,
+ @ForceDarkTypeDef int expectedForceDarkType) {
+ var uiModeManager = sContext.getSystemService(UiModeManager.class);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ uiModeManager.setApplicationNightMode(
+ isAppInNightMode ? MODE_NIGHT_YES : MODE_NIGHT_NO);
+ Settings.Secure.putInt(
+ sContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+ isForceInvertEnabled ? 1 : 0);
+ });
+
+ sInstrumentation.runOnMainSync(() ->
+ mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
+ try {
+ TestUtils.waitUntil("Waiting for force invert state changed",
+ () -> (uiModeManager.getForceInvertState() == expectedForceInvertType));
+ } catch (Exception e) {
+ Log.e(TAG, "Unexpected error trying to apply force invert state. " + e);
+ e.printStackTrace();
+ }
+
+ mExpect.that(mViewRootImpl.determineForceDarkType()).isEqualTo(expectedForceDarkType);
+ }
}
diff --git a/core/tests/featureflagtests/OWNERS b/core/tests/featureflagtests/OWNERS
index 2ff4f5ab8807..6784f2891009 100644
--- a/core/tests/featureflagtests/OWNERS
+++ b/core/tests/featureflagtests/OWNERS
@@ -1,2 +1 @@
-sbasi@google.com
-tmfang@google.com \ No newline at end of file
+tmfang@google.com
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index 712042f6ff6b..1251fce1ce19 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1,6 +1,5 @@
include /PACKAGE_MANAGER_OWNERS
-cbrubaker@google.com
hackbod@android.com
hackbod@google.com
jeffv@google.com
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 15f70298198f..9234902335c1 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -619,6 +619,8 @@ applications that come with the platform
<permission name="android.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE"/>
<permission name="android.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE"/>
<permission name="android.permission.READ_COLOR_ZONES"/>
+ <!-- Permission required for CTS test - CtsTextClassifierTestCases -->
+ <permission name="android.permission.ACCESS_TEXT_CLASSIFIER_BY_TYPE"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/drm/java/android/drm/OWNERS b/drm/java/android/drm/OWNERS
index 43871001c9ad..b65cce70225e 100644
--- a/drm/java/android/drm/OWNERS
+++ b/drm/java/android/drm/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 49079
-jtinker@google.com
robertshih@google.com
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index a0ca0988e03c..05e23a08481f 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -2206,26 +2206,21 @@ public class Paint {
* @param fontVariationOverride font variation override. You can pass null or empty string for
* clearing font variation override.
*
- * @return true if the provided font variation settings is valid. Otherwise returns false.
- *
+ * @throws IllegalArgumentException If given string is not a valid font variation settings
+ * format
* @see #getFontVariationSettings()
* @see #setFontVariationSettings(String)
* @see #getFontVariationOverride()
* @see FontVariationAxis
*/
@FlaggedApi(FLAG_TYPEFACE_REDESIGN_READONLY)
- public boolean setFontVariationOverride(@Nullable String fontVariationOverride) {
+ public void setFontVariationOverride(@Nullable String fontVariationOverride) {
if (Objects.equals(fontVariationOverride, mFontVariationOverride)) {
- return true;
+ return;
}
- List<FontVariationAxis> axes;
- try {
- axes = FontVariationAxis.fromFontVariationSettingsForList(fontVariationOverride);
- } catch (IllegalArgumentException e) {
- Log.i(TAG, "failed to parse font variation settings.", e);
- return false;
- }
+ List<FontVariationAxis> axes =
+ FontVariationAxis.fromFontVariationSettingsForList(fontVariationOverride);
long builderPtr = nCreateFontVariationBuilder(axes.size());
for (int i = 0; i < axes.size(); ++i) {
FontVariationAxis axis = axes.get(i);
@@ -2234,7 +2229,6 @@ public class Paint {
}
nSetFontVariationOverride(mNativePaint, builderPtr);
mFontVariationOverride = fontVariationOverride;
- return true;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
index 6207e5b020f7..7e557860365e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
@@ -4,5 +4,4 @@ madym@google.com
mattsziklay@google.com
mdehaini@google.com
pbdr@google.com
-tkachenkoi@google.com
vaniadesmonda@google.com
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 305fcdd5fb7d..be2240286ab1 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
@@ -117,6 +117,7 @@ import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation.UpdateSource;
import com.android.wm.shell.shared.bubbles.BubbleBarUpdate;
import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider;
import com.android.wm.shell.shared.bubbles.DeviceConfig;
@@ -795,7 +796,7 @@ public class BubbleController implements ConfigurationChangeListener,
* Update bubble bar location and trigger and update to listeners
*/
public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation,
- @BubbleBarLocation.UpdateSource int source) {
+ @UpdateSource int source) {
if (isShowingAsBubbleBar()) {
updateExpandedViewForBubbleBarLocation(bubbleBarLocation, source);
BubbleBarUpdate bubbleBarUpdate = new BubbleBarUpdate();
@@ -805,7 +806,7 @@ public class BubbleController implements ConfigurationChangeListener,
}
private void updateExpandedViewForBubbleBarLocation(BubbleBarLocation bubbleBarLocation,
- @BubbleBarLocation.UpdateSource int source) {
+ @UpdateSource int source) {
if (isShowingAsBubbleBar()) {
BubbleBarLocation previousLocation = mBubblePositioner.getBubbleBarLocation();
mBubblePositioner.setBubbleBarLocation(bubbleBarLocation);
@@ -818,7 +819,7 @@ public class BubbleController implements ConfigurationChangeListener,
private void logBubbleBarLocationIfChanged(BubbleBarLocation location,
BubbleBarLocation previous,
- @BubbleBarLocation.UpdateSource int source) {
+ @UpdateSource int source) {
if (mLayerView == null) {
return;
}
@@ -830,25 +831,25 @@ public class BubbleController implements ConfigurationChangeListener,
return;
}
switch (source) {
- case BubbleBarLocation.UpdateSource.DRAG_BAR:
- case BubbleBarLocation.UpdateSource.A11Y_ACTION_BAR:
+ case UpdateSource.DRAG_BAR:
+ case UpdateSource.A11Y_ACTION_BAR:
mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_DRAG_BAR
: BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_DRAG_BAR);
break;
- case BubbleBarLocation.UpdateSource.DRAG_BUBBLE:
- case BubbleBarLocation.UpdateSource.A11Y_ACTION_BUBBLE:
+ case UpdateSource.DRAG_BUBBLE:
+ case UpdateSource.A11Y_ACTION_BUBBLE:
mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_DRAG_BUBBLE
: BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_DRAG_BUBBLE);
break;
- case BubbleBarLocation.UpdateSource.DRAG_EXP_VIEW:
- case BubbleBarLocation.UpdateSource.A11Y_ACTION_EXP_VIEW:
+ case UpdateSource.DRAG_EXP_VIEW:
+ case UpdateSource.A11Y_ACTION_EXP_VIEW:
// TODO(b/349845968): move logging from BubbleBarLayerView to here
break;
- case BubbleBarLocation.UpdateSource.APP_ICON_DRAG:
+ case UpdateSource.APP_ICON_DRAG:
mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_APP_ICON_DROP
: BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_APP_ICON_DROP);
break;
- case BubbleBarLocation.UpdateSource.DRAG_TASK:
+ case UpdateSource.DRAG_TASK:
mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_DRAG_TASK
: BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_DRAG_TASK);
break;
@@ -872,10 +873,7 @@ public class BubbleController implements ConfigurationChangeListener,
if (bubbleBarLocation == null) return;
if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) {
mBubbleStateListener.onDragItemOverBubbleBarDragZone(bubbleBarLocation);
- ensureBubbleViewsAndWindowCreated();
- if (mLayerView != null) {
- mLayerView.showBubbleBarExtendedViewDropTarget(bubbleBarLocation);
- }
+ showBubbleBarExpandedViewDropTarget(bubbleBarLocation);
}
}
@@ -921,6 +919,13 @@ public class BubbleController implements ConfigurationChangeListener,
return result;
}
+ private void showBubbleBarExpandedViewDropTarget(BubbleBarLocation bubbleBarLocation) {
+ ensureBubbleViewsAndWindowCreated();
+ if (mLayerView != null) {
+ mLayerView.showBubbleBarExtendedViewDropTarget(bubbleBarLocation);
+ }
+ }
+
private void hideBubbleBarExpandedViewDropTarget() {
if (mLayerView != null) {
mLayerView.hideBubbleBarExpandedViewDropTarget();
@@ -1541,20 +1546,9 @@ public class BubbleController implements ConfigurationChangeListener,
public void expandStackAndSelectBubble(ShortcutInfo info,
@Nullable BubbleBarLocation bubbleBarLocation) {
if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
- BubbleBarLocation updateLocation = isShowingAsBubbleBar() ? bubbleBarLocation : null;
- if (updateLocation != null) {
- updateExpandedViewForBubbleBarLocation(updateLocation,
- BubbleBarLocation.UpdateSource.APP_ICON_DRAG);
- }
Bubble b = mBubbleData.getOrCreateBubble(info); // Removes from overflow
ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - shortcut=%s", info);
- if (b.isInflated()) {
- mBubbleData.setSelectedBubbleAndExpandStack(b, updateLocation);
- } else {
- b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
- inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false,
- updateLocation);
- }
+ expandStackAndSelectAppBubble(b, bubbleBarLocation, UpdateSource.APP_ICON_DRAG);
}
/**
@@ -1562,16 +1556,12 @@ public class BubbleController implements ConfigurationChangeListener,
*
* @param intent the intent for the bubble.
*/
- public void expandStackAndSelectBubble(Intent intent, UserHandle user) {
+ public void expandStackAndSelectBubble(Intent intent, UserHandle user,
+ @Nullable BubbleBarLocation bubbleBarLocation) {
if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
Bubble b = mBubbleData.getOrCreateBubble(intent, user); // Removes from overflow
ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", intent);
- if (b.isInflated()) {
- mBubbleData.setSelectedBubbleAndExpandStack(b);
- } else {
- b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
- inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
- }
+ expandStackAndSelectAppBubble(b, bubbleBarLocation, UpdateSource.APP_ICON_DRAG);
}
/**
@@ -1583,14 +1573,19 @@ public class BubbleController implements ConfigurationChangeListener,
public void expandStackAndSelectBubble(PendingIntent pendingIntent, UserHandle user,
@Nullable BubbleBarLocation bubbleBarLocation) {
if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
+ Bubble b = mBubbleData.getOrCreateBubble(pendingIntent, user); // Removes from overflow
+ ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - pendingIntent=%s",
+ pendingIntent);
+ expandStackAndSelectAppBubble(b, bubbleBarLocation, UpdateSource.APP_ICON_DRAG);
+ }
+
+ private void expandStackAndSelectAppBubble(Bubble b,
+ @Nullable BubbleBarLocation bubbleBarLocation, @UpdateSource int source) {
+ if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
BubbleBarLocation updateLocation = isShowingAsBubbleBar() ? bubbleBarLocation : null;
if (updateLocation != null) {
- updateExpandedViewForBubbleBarLocation(updateLocation,
- BubbleBarLocation.UpdateSource.APP_ICON_DRAG);
+ updateExpandedViewForBubbleBarLocation(updateLocation, source);
}
- Bubble b = mBubbleData.getOrCreateBubble(pendingIntent, user);
- ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - pendingIntent=%s",
- pendingIntent);
if (b.isInflated()) {
mBubbleData.setSelectedBubbleAndExpandStack(b, updateLocation);
} else {
@@ -1623,7 +1618,7 @@ public class BubbleController implements ConfigurationChangeListener,
}
} else {
if (location != null) {
- setBubbleBarLocation(location, BubbleBarLocation.UpdateSource.DRAG_TASK);
+ setBubbleBarLocation(location, UpdateSource.DRAG_TASK);
}
b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
// Lazy init stack view when a bubble is created
@@ -2840,14 +2835,16 @@ public class BubbleController implements ConfigurationChangeListener,
}
@Override
- public void showShortcutBubble(ShortcutInfo info) {
+ public void showShortcutBubble(ShortcutInfo info, @Nullable BubbleBarLocation location) {
mMainExecutor.execute(() -> mController
- .expandStackAndSelectBubble(info, /* bubbleBarLocation = */ null));
+ .expandStackAndSelectBubble(info, location));
}
@Override
- public void showAppBubble(Intent intent, UserHandle user) {
- mMainExecutor.execute(() -> mController.expandStackAndSelectBubble(intent, user));
+ public void showAppBubble(Intent intent, UserHandle user,
+ @Nullable BubbleBarLocation location) {
+ mMainExecutor.execute(
+ () -> mController.expandStackAndSelectBubble(intent, user, location));
}
@Override
@@ -2900,7 +2897,7 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
public void setBubbleBarLocation(BubbleBarLocation location,
- @BubbleBarLocation.UpdateSource int source) {
+ @UpdateSource int source) {
mMainExecutor.execute(() ->
mController.setBubbleBarLocation(location, source));
}
@@ -2921,6 +2918,17 @@ public class BubbleController implements ConfigurationChangeListener,
}
});
}
+
+ @Override
+ public void showDropTarget(boolean show, BubbleBarLocation location) {
+ mMainExecutor.execute(() -> {
+ if (show) {
+ showBubbleBarExpandedViewDropTarget(location);
+ } else {
+ hideBubbleBarExpandedViewDropTarget();
+ }
+ });
+ }
}
private class BubblesImpl implements Bubbles {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index 0a4d79a6c297..ae1b4077098d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -51,9 +51,11 @@ interface IBubbles {
oneway void stopBubbleDrag(in BubbleBarLocation location, in int topOnScreen) = 11;
- oneway void showShortcutBubble(in ShortcutInfo info) = 12;
+ oneway void showShortcutBubble(in ShortcutInfo info, in @nullable BubbleBarLocation location) = 12;
- oneway void showAppBubble(in Intent intent, in UserHandle user) = 13;
+ oneway void showAppBubble(in Intent intent, in UserHandle user, in @nullable BubbleBarLocation location) = 13;
oneway void showExpandedView() = 14;
+
+ oneway void showDropTarget(in boolean show, in @nullable BubbleBarLocation location) = 15;
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
index b507ca2019a9..3f21e74a7d03 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.app.ActivityManager;
+import android.window.DesktopExperienceFlags;
import android.window.DisplayAreaInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -67,7 +68,7 @@ public class PipDesktopState {
/** Returns whether PiP in Connected Displays is enabled by checking the flag. */
public boolean isConnectedDisplaysPipEnabled() {
- return Flags.enableConnectedDisplaysPip();
+ return DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_PIP.isTrue();
}
/** Returns whether the display with the PiP task is in freeform windowing mode. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt
index 7074e8bc9cce..6c6d830e915e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandler.kt
@@ -21,6 +21,7 @@ import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.os.Handler
import android.os.IBinder
import android.view.SurfaceControl.Transaction
+import android.view.WindowManager.TRANSIT_TO_BACK
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
@@ -61,7 +62,9 @@ class DesktopMinimizationTransitionHandler(
finishTransaction: Transaction,
finishCallback: Transitions.TransitionFinishCallback,
): Boolean {
- if (!TransitionUtil.isClosingType(info.type)) return false
+ val shouldAnimate =
+ TransitionUtil.isClosingType(info.type) || info.type == Transitions.TRANSIT_MINIMIZE
+ if (!shouldAnimate) return false
val animations = mutableListOf<Animator>()
val onAnimFinish: (Animator) -> Unit = { animator ->
@@ -75,10 +78,14 @@ class DesktopMinimizationTransitionHandler(
}
}
+ val checkChangeMode = { change: TransitionInfo.Change ->
+ change.mode == info.type ||
+ (info.type == Transitions.TRANSIT_MINIMIZE && change.mode == TRANSIT_TO_BACK)
+ }
animations +=
info.changes
.filter {
- it.mode == info.type && it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM
+ checkChangeMode(it) && it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM
}
.mapNotNull { createMinimizeAnimation(it, finishTransaction, onAnimFinish) }
if (animations.isEmpty()) return false
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
index aa507728739e..e3a71a1ad9a5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt
@@ -18,6 +18,7 @@ package com.android.wm.shell.desktopmode
import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.window.DesktopExperienceFlags
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource.UNKNOWN
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.transition.FocusTransitionObserver
@@ -188,8 +189,12 @@ class DesktopModeShellCommandHandler(
pw.println("Error: task id should be an integer")
return false
}
- pw.println("Not implemented.")
- return false
+ controller.moveTaskToFront(
+ /* taskId= */ taskId,
+ /* remoteTransition= */ null,
+ /* unminimizeReason= */ UnminimizeReason.UNKNOWN,
+ )
+ return true
}
private fun runMoveTaskOutOfDesk(args: Array<String>, pw: PrintWriter): Boolean {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
index 6034299453fb..70a648f57125 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
@@ -35,7 +35,7 @@ class DesktopTaskChangeListener(private val desktopUserRepositories: DesktopUser
desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
return
}
- if (isFreeformTask(taskInfo)) {
+ if (isFreeformTask(taskInfo) && !desktopRepository.isActiveTask(taskInfo.taskId)) {
desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
}
}
@@ -44,23 +44,33 @@ class DesktopTaskChangeListener(private val desktopUserRepositories: DesktopUser
logD("onTaskChanging for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
val desktopRepository: DesktopRepository =
desktopUserRepositories.getProfile(taskInfo.userId)
- if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
-
// TODO: b/394281403 - with multiple desks, it's possible to have a non-freeform task
// inside a desk, so this should be decoupled from windowing mode.
// Also, changes in/out of desks are handled by the [DesksTransitionObserver], which has
// more specific information about the desk involved in the transition, which might be
// more accurate than assuming it's always the default/active desk in the display, as this
// method does.
- // Case 1: Freeform task is changed in Desktop Mode.
- if (isFreeformTask(taskInfo)) {
- if (taskInfo.isVisible) {
+ // Case 1: When the task change is from a task in the desktop repository which is now
+ // fullscreen,
+ // remove the task from the desktop repository since it is no longer a freeform task.
+ if (!isFreeformTask(taskInfo)) {
+ if (desktopRepository.isActiveTask(taskInfo.taskId)) {
+ desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
+ }
+ } else { // Task change is a freeform task
+ if (!desktopRepository.isActiveTask(taskInfo.taskId)) {
+ // Case 2: When the task change is a freeform visible task, but the task is not
+ // yet active in the desktop repository, adds task to desktop repository.
desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
+ } else {
+ // Case 3: When the task change is a freeform task which already exists as an active
+ // task in the desktop repository, updates the task state.
+ desktopRepository.updateTask(
+ taskInfo.displayId,
+ taskInfo.taskId,
+ taskInfo.isVisible,
+ )
}
- desktopRepository.updateTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
- } else {
- // Case 2: Freeform task is changed outside Desktop Mode.
- desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
}
}
@@ -82,14 +92,22 @@ class DesktopTaskChangeListener(private val desktopUserRepositories: DesktopUser
logD("onTaskMovingToFront for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
val desktopRepository: DesktopRepository =
desktopUserRepositories.getProfile(taskInfo.userId)
- if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
- if (!isFreeformTask(taskInfo)) {
+ // When the task change is from a task in the desktop repository which is now fullscreen,
+ // remove the task from the desktop repository since it is no longer a freeform task.
+ if (!isFreeformTask(taskInfo) && desktopRepository.isActiveTask(taskInfo.taskId)) {
desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
}
- desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
+ if (isFreeformTask(taskInfo)) {
+ // If the task is already active in the repository, then it only moves the task to the
+ // front.
+ desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
+ }
}
override fun onTaskMovingToBack(taskInfo: RunningTaskInfo) {
+ val desktopRepository: DesktopRepository =
+ desktopUserRepositories.getProfile(taskInfo.userId)
+ if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
logD("onTaskMovingToBack for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
// TODO: b/367268953 - Connect this with DesktopRepository.
}
@@ -101,7 +119,7 @@ class DesktopTaskChangeListener(private val desktopUserRepositories: DesktopUser
if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
// TODO: b/370038902 - Handle Activity#finishAndRemoveTask.
if (
- !DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue() ||
+ !DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue ||
desktopRepository.isClosingTask(taskInfo.taskId)
) {
// A task that's vanishing should be removed:
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 b47dfe2064cd..8f7e52ea2108 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
@@ -677,11 +677,7 @@ class DesktopTasksController(
// Bring other apps to front first.
bringDesktopAppsToFrontBeforeShowingNewTask(displayId, wct, task.taskId)
}
- if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
- prepareMoveTaskToDesk(wct, task, deskId)
- } else {
- addMoveToDesktopChanges(wct, task)
- }
+ addMoveToDeskTaskChanges(wct = wct, task = task, deskId = deskId)
return taskIdToMinimize
}
@@ -1121,12 +1117,13 @@ class DesktopTasksController(
excludeTaskId = launchingTaskId,
reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH,
)
- var deskIdToActivate: Int? = null
- if (
- DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue &&
+ var activationRunOnTransitStart: RunOnTransitStart? = null
+ val shouldActivateDesk =
+ (DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue ||
+ DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) &&
!isDesktopModeShowing(displayId)
- ) {
- deskIdToActivate =
+ if (shouldActivateDesk) {
+ val deskIdToActivate =
checkNotNull(
launchingTaskId?.let { taskRepository.getDeskIdForTask(it) }
?: getDefaultDeskId(displayId)
@@ -1136,6 +1133,18 @@ class DesktopTasksController(
// Desk activation must be handled before app launch-related transactions.
activateDeskWct.merge(launchTransaction, /* transfer= */ true)
launchTransaction = activateDeskWct
+ activationRunOnTransitStart = { transition ->
+ desksTransitionObserver.addPendingTransition(
+ DeskTransition.ActivateDesk(
+ token = transition,
+ displayId = displayId,
+ deskId = deskIdToActivate,
+ )
+ )
+ }
+ desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(
+ FREEFORM_ANIMATION_DURATION
+ )
}
val t =
if (remoteTransition == null) {
@@ -1169,24 +1178,7 @@ class DesktopTasksController(
if (launchingTaskId != null && taskRepository.isMinimizedTask(launchingTaskId)) {
addPendingUnminimizeTransition(t, displayId, launchingTaskId, unminimizeReason)
}
- if (
- DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue &&
- deskIdToActivate != null
- ) {
- if (DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue) {
- desksTransitionObserver.addPendingTransition(
- DeskTransition.ActivateDesk(
- token = t,
- displayId = displayId,
- deskId = deskIdToActivate,
- )
- )
- }
-
- desktopModeEnterExitTransitionListener?.onEnterDesktopModeTransitionStarted(
- FREEFORM_ANIMATION_DURATION
- )
- }
+ activationRunOnTransitStart?.invoke(t)
exitImmersiveResult.asExit()?.runOnTransitionStart?.invoke(t)
return t
}
@@ -1250,6 +1242,10 @@ class DesktopTasksController(
pendingIntentBackgroundActivityStartMode =
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
launchBounds = bounds
+ if (DesktopModeFlags.ENABLE_SHELL_INITIAL_BOUNDS_REGRESSION_BUG_FIX.isTrue) {
+ // Sets launch bounds size as flexible so core can recalculate.
+ flexibleLaunchSize = true
+ }
}
wct.sendPendingIntent(pendingIntent, intent, ops.toBundle())
@@ -1260,6 +1256,8 @@ class DesktopTasksController(
* Move [task] to display with [displayId].
*
* No-op if task is already on that display per [RunningTaskInfo.displayId].
+ *
+ * TODO: b/399411604 - split this up into smaller functions.
*/
private fun moveToDisplay(task: RunningTaskInfo, displayId: Int) {
logV("moveToDisplay: taskId=%d displayId=%d", task.taskId, displayId)
@@ -1315,16 +1313,20 @@ class DesktopTasksController(
// TODO: b/393977830 and b/397437641 - do not assume that freeform==desktop.
if (!task.isFreeform) {
- addMoveToDesktopChanges(wct, task, displayId)
- } else if (Flags.enableMoveToNextDisplayShortcut()) {
- applyFreeformDisplayChange(wct, task, displayId)
+ addMoveToDeskTaskChanges(wct = wct, task = task, deskId = destinationDeskId)
+ } else {
+ if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+ desksOrganizer.moveTaskToDesk(wct, destinationDeskId, task)
+ }
+ if (Flags.enableMoveToNextDisplayShortcut()) {
+ applyFreeformDisplayChange(wct, task, displayId)
+ }
}
- if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
- desksOrganizer.moveTaskToDesk(wct, destinationDeskId, task)
- } else {
+ if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
wct.reparent(task.token, displayAreaInfo.token, /* onTop= */ true)
}
+
addDeskActivationChanges(destinationDeskId, wct)
val activationRunnable: RunOnTransitStart = { transition ->
desksTransitionObserver.addPendingTransition(
@@ -2062,12 +2064,13 @@ class DesktopTasksController(
triggerTask?.let { task ->
when {
// Check if freeform task launch during recents should be handled
- shouldHandleMidRecentsFreeformLaunch -> handleMidRecentsFreeformTaskLaunch(task)
+ shouldHandleMidRecentsFreeformLaunch ->
+ handleMidRecentsFreeformTaskLaunch(task, transition)
// Check if the closing task needs to be handled
TransitionUtil.isClosingType(request.type) ->
handleTaskClosing(task, transition, request.type)
// Check if the top task shouldn't be allowed to enter desktop mode
- isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task)
+ isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task, transition)
// Check if fullscreen task should be updated
task.isFullscreen -> handleFullscreenTaskLaunch(task, transition)
// Check if freeform task should be updated
@@ -2306,20 +2309,23 @@ class DesktopTasksController(
* This is a special case where we want to launch the task in fullscreen instead of freeform.
*/
private fun handleMidRecentsFreeformTaskLaunch(
- task: RunningTaskInfo
+ task: RunningTaskInfo,
+ transition: IBinder,
): WindowContainerTransaction? {
logV("DesktopTasksController: handleMidRecentsFreeformTaskLaunch")
val wct = WindowContainerTransaction()
- addMoveToFullscreenChanges(
- wct = wct,
- taskInfo = task,
- willExitDesktop =
- willExitDesktop(
- triggerTaskId = task.taskId,
- displayId = task.displayId,
- forceExitDesktop = true,
- ),
- )
+ val runOnTransitStart =
+ addMoveToFullscreenChanges(
+ wct = wct,
+ taskInfo = task,
+ willExitDesktop =
+ willExitDesktop(
+ triggerTaskId = task.taskId,
+ displayId = task.displayId,
+ forceExitDesktop = true,
+ ),
+ )
+ runOnTransitStart?.invoke(transition)
wct.reorder(task.token, true)
return wct
}
@@ -2343,16 +2349,18 @@ class DesktopTasksController(
// launched. We should make this task go to fullscreen instead of freeform. Note
// that this means any re-launch of a freeform window outside of desktop will be in
// fullscreen as long as default-desktop flag is disabled.
- addMoveToFullscreenChanges(
- wct = wct,
- taskInfo = task,
- willExitDesktop =
- willExitDesktop(
- triggerTaskId = task.taskId,
- displayId = task.displayId,
- forceExitDesktop = true,
- ),
- )
+ val runOnTransitStart =
+ addMoveToFullscreenChanges(
+ wct = wct,
+ taskInfo = task,
+ willExitDesktop =
+ willExitDesktop(
+ triggerTaskId = task.taskId,
+ displayId = task.displayId,
+ forceExitDesktop = true,
+ ),
+ )
+ runOnTransitStart?.invoke(transition)
return wct
}
bringDesktopAppsToFrontBeforeShowingNewTask(task.displayId, wct, task.taskId)
@@ -2416,7 +2424,8 @@ class DesktopTasksController(
if (shouldFullscreenTaskLaunchSwitchToDesktop(task)) {
logD("Switch fullscreen task to freeform on transition: taskId=%d", task.taskId)
return WindowContainerTransaction().also { wct ->
- addMoveToDesktopChanges(wct, task)
+ val deskId = getDefaultDeskId(task.displayId)
+ addMoveToDeskTaskChanges(wct = wct, task = task, deskId = deskId)
// In some launches home task is moved behind new task being launched. Make sure
// that's not the case for launches in desktop. Also, if this launch is the first
// one to trigger the desktop mode (e.g., when [forceEnterDesktop()]), activate the
@@ -2447,7 +2456,8 @@ class DesktopTasksController(
// If a freeform task receives a request for a fullscreen launch, apply the same
// changes we do for similar transitions. The task not having WINDOWING_MODE_UNDEFINED
// set when needed can interfere with future split / multi-instance transitions.
- return WindowContainerTransaction().also { wct ->
+ val wct = WindowContainerTransaction()
+ val runOnTransitStart =
addMoveToFullscreenChanges(
wct = wct,
taskInfo = task,
@@ -2458,7 +2468,8 @@ class DesktopTasksController(
forceExitDesktop = true,
),
)
- }
+ runOnTransitStart?.invoke(transition)
+ return wct
}
return null
}
@@ -2473,7 +2484,10 @@ class DesktopTasksController(
* If a task is not compatible with desktop mode freeform, it should always be launched in
* fullscreen.
*/
- private fun handleIncompatibleTaskLaunch(task: RunningTaskInfo): WindowContainerTransaction? {
+ private fun handleIncompatibleTaskLaunch(
+ task: RunningTaskInfo,
+ transition: IBinder,
+ ): WindowContainerTransaction? {
logV("handleIncompatibleTaskLaunch")
if (!isDesktopModeShowing(task.displayId) && !forceEnterDesktop(task.displayId)) return null
// Only update task repository for transparent task.
@@ -2485,7 +2499,8 @@ class DesktopTasksController(
}
// Already fullscreen, no-op.
if (task.isFullscreen) return null
- return WindowContainerTransaction().also { wct ->
+ val wct = WindowContainerTransaction()
+ val runOnTransitStart =
addMoveToFullscreenChanges(
wct = wct,
taskInfo = task,
@@ -2496,7 +2511,8 @@ class DesktopTasksController(
forceExitDesktop = true,
),
)
- }
+ runOnTransitStart?.invoke(transition)
+ return wct
}
/**
@@ -2543,55 +2559,44 @@ class DesktopTasksController(
}
/**
- * Apply all changes required when task is first added to desktop. Uses the task's current
- * display by default to apply initial bounds and placement relative to the display. Use a
- * different [displayId] if the task should be moved to a different display.
+ * Applies the [wct] changes needed when a task is first moving to a desk.
+ *
+ * Note that this recalculates the initial bounds of the task, so it should not be used when
+ * transferring a task between desks.
+ *
+ * TODO: b/362720497 - this should be improved to be reusable by desk-to-desk CUJs where
+ * [DesksOrganizer.moveTaskToDesk] needs to be called and even cross-display CUJs where
+ * [applyFreeformDisplayChange] needs to be called. Potentially by comparing source vs
+ * destination desk ids and display ids, or adding extra arguments to the function.
*/
- @VisibleForTesting
- @Deprecated("Deprecated with multiple desks", ReplaceWith("prepareMoveTaskToDesk()"))
- fun addMoveToDesktopChanges(
+ fun addMoveToDeskTaskChanges(
wct: WindowContainerTransaction,
- taskInfo: RunningTaskInfo,
- displayId: Int = taskInfo.displayId,
- ) {
- val displayLayout = displayController.getDisplayLayout(displayId) ?: return
- val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)!!
- val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
- // TODO: b/397437641 - reconsider the windowing mode choice when multiple desks is enabled.
- val targetWindowingMode =
- if (tdaWindowingMode == WINDOWING_MODE_FREEFORM) {
- // Display windowing is freeform, set to undefined and inherit it
- WINDOWING_MODE_UNDEFINED
- } else {
- WINDOWING_MODE_FREEFORM
- }
- val initialBounds = getInitialBounds(displayLayout, taskInfo, displayId)
-
- if (canChangeTaskPosition(taskInfo)) {
- wct.setBounds(taskInfo.token, initialBounds)
- }
- wct.setWindowingMode(taskInfo.token, targetWindowingMode)
- wct.reorder(taskInfo.token, /* onTop= */ true)
- if (useDesktopOverrideDensity()) {
- wct.setDensityDpi(taskInfo.token, DESKTOP_DENSITY_OVERRIDE)
- }
- }
-
- private fun prepareMoveTaskToDesk(
- wct: WindowContainerTransaction,
- taskInfo: RunningTaskInfo,
+ task: RunningTaskInfo,
deskId: Int,
) {
- if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) return
- val displayId = taskRepository.getDisplayForDesk(deskId)
- val displayLayout = displayController.getDisplayLayout(displayId) ?: return
- val initialBounds = getInitialBounds(displayLayout, taskInfo, displayId)
- if (canChangeTaskPosition(taskInfo)) {
- wct.setBounds(taskInfo.token, initialBounds)
+ val targetDisplayId = taskRepository.getDisplayForDesk(deskId)
+ val displayLayout = displayController.getDisplayLayout(targetDisplayId) ?: return
+ val initialBounds = getInitialBounds(displayLayout, task, targetDisplayId)
+ if (canChangeTaskPosition(task)) {
+ wct.setBounds(task.token, initialBounds)
+ }
+ if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
+ desksOrganizer.moveTaskToDesk(wct = wct, deskId = deskId, task = task)
+ } else {
+ val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(targetDisplayId)!!
+ val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode
+ val targetWindowingMode =
+ if (tdaWindowingMode == WINDOWING_MODE_FREEFORM) {
+ // Display windowing is freeform, set to undefined and inherit it
+ WINDOWING_MODE_UNDEFINED
+ } else {
+ WINDOWING_MODE_FREEFORM
+ }
+ wct.setWindowingMode(task.token, targetWindowingMode)
+ wct.reorder(task.token, /* onTop= */ true)
}
- desksOrganizer.moveTaskToDesk(wct, deskId = deskId, task = taskInfo)
if (useDesktopOverrideDensity()) {
- wct.setDensityDpi(taskInfo.token, DESKTOP_DENSITY_OVERRIDE)
+ wct.setDensityDpi(task.token, DESKTOP_DENSITY_OVERRIDE)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
index 44d46eea9c55..7a63ec5eeda3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
@@ -2,7 +2,6 @@
atsjenk@google.com
jorgegil@google.com
madym@google.com
-nmusgrave@google.com
pbdr@google.com
vaniadesmonda@google.com
pragyabajoria@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index d666126b91ba..c0a0f469add4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
+import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -200,7 +201,8 @@ public class KeyguardTransitionHandler
transition, info, startTransaction, finishTransaction, finishCallback);
}
- if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0) {
+ if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0
+ || (info.getFlags() & TRANSIT_FLAG_AOD_APPEARING) != 0) {
return startAnimation(mAppearTransition, "appearing",
transition, info, startTransaction, finishTransaction, finishCallback);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/OWNERS
index 5aa3c4e2abef..245669b644db 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/OWNERS
@@ -1,3 +1,2 @@
# WM shell sub-module TV pip owner
-galinap@google.com
bronger@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
index 1ce24f76ada5..6012fe66188d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
@@ -32,6 +32,7 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.SurfaceControl;
+import android.window.DesktopExperienceFlags;
import android.window.DisplayAreaInfo;
import android.window.WindowContainerTransaction;
@@ -41,7 +42,6 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.Preconditions;
-import com.android.window.flags.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayChangeController;
@@ -303,7 +303,8 @@ public class PipController implements ConfigurationChangeListener,
public void onDisplayRemoved(int displayId) {
// If PiP was active on an external display that is removed, clean up states and set
// {@link PipDisplayLayoutState} to DEFAULT_DISPLAY.
- if (Flags.enableConnectedDisplaysPip() && mPipTransitionState.isInPip()
+ if (DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_PIP.isTrue()
+ && mPipTransitionState.isInPip()
&& displayId == mPipDisplayLayoutState.getDisplayId()
&& displayId != DEFAULT_DISPLAY) {
mPipTransitionState.setState(PipTransitionState.EXITING_PIP);
@@ -345,7 +346,6 @@ public class PipController implements ConfigurationChangeListener,
return;
}
- mPipTouchHandler.updateMinMaxSize(mPipBoundsState.getAspectRatio());
mPipMenuController.hideMenu();
if (mPipTransitionState.isInFixedRotation()) {
@@ -366,6 +366,8 @@ public class PipController implements ConfigurationChangeListener,
mPipBoundsState.setBounds(toBounds);
}
t.setBounds(mPipTransitionState.getPipTaskToken(), mPipBoundsState.getBounds());
+ // Update the size spec in PipBoundsState afterwards.
+ mPipBoundsState.updateMinMaxSize(mPipBoundsState.getAspectRatio());
}
private void setDisplayLayout(DisplayLayout layout) {
@@ -384,7 +386,7 @@ public class PipController implements ConfigurationChangeListener,
// If PiP is enabled on Connected Displays, update PipDisplayLayoutState to have the correct
// display info that PiP is entering in.
- if (Flags.enableConnectedDisplaysPip()) {
+ if (DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_PIP.isTrue()) {
final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(displayId);
if (displayLayout != null) {
mPipDisplayLayoutState.setDisplayId(displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java
index af1e98a3a8d2..d53365abd143 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java
@@ -81,8 +81,6 @@ public class PipResizeGestureHandler implements
private final PointF mDownSecondPoint = new PointF();
private final PointF mLastPoint = new PointF();
private final PointF mLastSecondPoint = new PointF();
- private final Point mMaxSize = new Point();
- private final Point mMinSize = new Point();
private final Rect mLastResizeBounds = new Rect();
private final Rect mUserResizeBounds = new Rect();
private final Rect mDownBounds = new Rect();
@@ -95,7 +93,6 @@ public class PipResizeGestureHandler implements
private boolean mIsEnabled;
private boolean mEnablePinchResize;
private boolean mEnableDragCornerResize;
- private boolean mIsSysUiStateValid;
private boolean mThresholdCrossed;
private boolean mOngoingPinchToResize = false;
private boolean mWaitingForBoundsChangeTransition = false;
@@ -152,7 +149,6 @@ public class PipResizeGestureHandler implements
}
void init() {
- mContext.getDisplay().getRealSize(mMaxSize);
reloadResources();
final Resources res = mContext.getResources();
@@ -163,15 +159,6 @@ public class PipResizeGestureHandler implements
reloadResources();
}
- /**
- * Called when SysUI state changed.
- *
- * @param isSysUiStateValid Is SysUI valid or not.
- */
- public void onSystemUiStateChanged(boolean isSysUiStateValid) {
- mIsSysUiStateValid = isSysUiStateValid;
- }
-
private void reloadResources() {
mPipDragToResizeHandler.reloadResources();
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
@@ -287,13 +274,15 @@ public class PipResizeGestureHandler implements
}
}
+ final Point minSize = mPipBoundsState.getMinSize();
+ final Point maxSize = mPipBoundsState.getMaxSize();
if (mOngoingPinchToResize) {
mPipPinchToResizeHandler.onPinchResize(mv, mDownPoint, mDownSecondPoint,
mDownBounds, mLastPoint, mLastSecondPoint, mLastResizeBounds, mTouchSlop,
- mMinSize, mMaxSize);
+ minSize, maxSize);
} else if (mEnableDragCornerResize) {
mPipDragToResizeHandler.onDragCornerResize(mv, mLastResizeBounds, mDownPoint,
- mDownBounds, mMinSize, mMaxSize, mTouchSlop);
+ mDownBounds, minSize, maxSize, mTouchSlop);
}
}
}
@@ -327,7 +316,7 @@ public class PipResizeGestureHandler implements
if (mEnablePinchResize && ev.getPointerCount() == 2) {
mPipPinchToResizeHandler.onPinchResize(ev, mDownPoint, mDownSecondPoint,
mDownBounds, mLastPoint, mLastSecondPoint, mLastResizeBounds,
- mTouchSlop, mMinSize, mMaxSize);
+ mTouchSlop, mPipBoundsState.getMinSize(), mPipBoundsState.getMaxSize());
mOngoingPinchToResize = mAllowGesture;
return mAllowGesture;
}
@@ -407,16 +396,19 @@ public class PipResizeGestureHandler implements
return;
}
+ final Point minSize = mPipBoundsState.getMinSize();
+ final Point maxSize = mPipBoundsState.getMaxSize();
+
// If user resize is pretty close to max size, just auto resize to max.
- if (mLastResizeBounds.width() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.x
- || mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.y) {
- resizeRectAboutCenter(mLastResizeBounds, mMaxSize.x, mMaxSize.y);
+ if (mLastResizeBounds.width() >= PINCH_RESIZE_AUTO_MAX_RATIO * maxSize.x
+ || mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * maxSize.y) {
+ resizeRectAboutCenter(mLastResizeBounds, maxSize.x, maxSize.y);
}
// If user resize is smaller than min size, auto resize to min
- if (mLastResizeBounds.width() < mMinSize.x
- || mLastResizeBounds.height() < mMinSize.y) {
- resizeRectAboutCenter(mLastResizeBounds, mMinSize.x, mMinSize.y);
+ if (mLastResizeBounds.width() < minSize.x
+ || mLastResizeBounds.height() < minSize.y) {
+ resizeRectAboutCenter(mLastResizeBounds, minSize.x, minSize.y);
}
// get the current movement bounds
@@ -472,15 +464,6 @@ public class PipResizeGestureHandler implements
mInputMonitor.pilferPointers();
}
-
- void updateMaxSize(int maxX, int maxY) {
- mMaxSize.set(maxX, maxY);
- }
-
- void updateMinSize(int minX, int minY) {
- mMinSize.set(minX, minY);
- }
-
void setOhmOffset(int offset) {
mOhmOffset = offset;
}
@@ -568,8 +551,6 @@ public class PipResizeGestureHandler implements
pw.println(innerPrefix + "mEnableDragCornerResize=" + mEnableDragCornerResize);
pw.println(innerPrefix + "mThresholdCrossed=" + mThresholdCrossed);
pw.println(innerPrefix + "mOhmOffset=" + mOhmOffset);
- pw.println(innerPrefix + "mMinSize=" + mMinSize);
- pw.println(innerPrefix + "mMaxSize=" + mMaxSize);
}
class PipResizeInputEventReceiver extends BatchedInputEventReceiver {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
index 72346b335a8e..6fdfecaf15d5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
@@ -230,10 +230,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha
pipBoundsState, mTouchState, mPipScheduler, mPipTransitionState, pipUiEventLogger,
menuController, this::getMovementBounds, mPipDisplayLayoutState, pipDesktopState,
mainExecutor, mPipPerfHintController);
- mPipBoundsState.addOnAspectRatioChangedCallback(aspectRatio -> {
- updateMinMaxSize(aspectRatio);
- onAspectRatioChanged();
- });
+ mPipBoundsState.addOnAspectRatioChangedCallback(aspectRatio -> onAspectRatioChanged());
mMoveOnShelVisibilityChanged = () -> {
if (mIsImeShowing && mImeHeight > mShelfHeight) {
@@ -418,15 +415,6 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha
mMainExecutor.executeDelayed(mMoveOnShelVisibilityChanged, PIP_KEEP_CLEAR_AREAS_DELAY);
}
- /**
- * Called when SysUI state changed.
- *
- * @param isSysUiStateValid Is SysUI valid or not.
- */
- public void onSystemUiStateChanged(boolean isSysUiStateValid) {
- mPipResizeGestureHandler.onSystemUiStateChanged(isSysUiStateValid);
- }
-
void adjustBoundsForRotation(Rect outBounds, Rect curBounds, Rect insetBounds) {
final Rect toMovementBounds = new Rect();
mPipBoundsAlgorithm.getMovementBounds(outBounds, insetBounds, toMovementBounds, 0);
@@ -480,8 +468,6 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha
mPipBoundsState.getExpandedBounds(), insetBounds, expandedMovementBounds,
bottomOffset);
- updatePipSizeConstraints(normalBounds, aspectRatio);
-
// The extra offset does not really affect the movement bounds, but are applied based on the
// current state (ime showing, or shelf offset) when we need to actually shift
int extraOffset = Math.max(
@@ -507,35 +493,6 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha
}
/**
- * Update the values for min/max allowed size of picture in picture window based on the aspect
- * ratio.
- * @param aspectRatio aspect ratio to use for the calculation of min/max size
- */
- public void updateMinMaxSize(float aspectRatio) {
- updatePipSizeConstraints(mPipBoundsState.getNormalBounds(),
- aspectRatio);
- }
-
- private void updatePipSizeConstraints(Rect normalBounds,
- float aspectRatio) {
- if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
- updatePinchResizeSizeConstraints(aspectRatio);
- } else {
- mPipResizeGestureHandler.updateMinSize(normalBounds.width(), normalBounds.height());
- mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getExpandedBounds().width(),
- mPipBoundsState.getExpandedBounds().height());
- }
- }
-
- private void updatePinchResizeSizeConstraints(float aspectRatio) {
- mPipBoundsState.updateMinMaxSize(aspectRatio);
- mPipResizeGestureHandler.updateMinSize(mPipBoundsState.getMinSize().x,
- mPipBoundsState.getMinSize().y);
- mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getMaxSize().x,
- mPipBoundsState.getMaxSize().y);
- }
-
- /**
* TODO Add appropriate description
*/
public void onRegistrationChanged(boolean isRegistered) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 93023471fdfb..a3a808de6ff1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2080,8 +2080,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
Math.max(topLeftBounds.top, 0);
bottomRightBounds.right =
Math.min(bottomRightBounds.right, mSplitLayout.getDisplayWidth());
- bottomRightBounds.top =
- Math.min(bottomRightBounds.top, mSplitLayout.getDisplayHeight());
+ bottomRightBounds.bottom =
+ Math.min(bottomRightBounds.bottom, mSplitLayout.getDisplayHeight());
// TODO (b/349828130): Can change to getState() fully after brief soak time.
if (mSplitState.get() != currentSnapPosition) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/OWNERS
index 28be0efc38f6..9dc0ebbb8e56 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/OWNERS
@@ -1,3 +1,2 @@
# WM shell sub-module TV splitscreen owner
-galinap@google.com
bronger@google.com
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 3652a1661f28..bf5800330979 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
@@ -95,7 +95,6 @@ import android.os.UserHandle;
import android.util.ArrayMap;
import android.view.SurfaceControl;
import android.view.WindowManager;
-import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.window.TransitionInfo;
import android.window.TransitionMetrics;
@@ -835,9 +834,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
a = mTransitionAnimation.loadVoiceActivityExitAnimation(enter, userId);
}
} else if (changeMode == TRANSIT_CHANGE) {
- // In the absence of a specific adapter, we just want to keep everything stationary.
- a = new AlphaAnimation(1.f, 1.f);
- a.setDuration(TransitionAnimation.DEFAULT_APP_TRANSITION_DURATION);
+ // Apply end state directly by default.
+ return null;
} else if (type == TRANSIT_RELAUNCH) {
a = mTransitionAnimation.createRelaunchAnimation(endBounds, mInsets, endBounds);
} else if (overrideType == ANIM_CUSTOM
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index 4c443d7501f7..d73d08c032f9 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -498,9 +498,9 @@ class DesktopModeFlickerScenarios {
it.remove(VisibleLayersShownMoreThanOneConsecutiveEntry())
} +
listOf(
- AppWindowOnTopAtStart(DESKTOP_MODE_APP),
AppWindowBecomesInvisible(DESKTOP_MODE_APP),
AppWindowOnTopAtEnd(LAUNCHER),
+ AppWindowIsInvisibleAtEnd(DESKTOP_WALLPAPER),
).associateBy({ it }, { AssertionInvocationGroup.BLOCKING })
)
val OPEN_UNLIMITED_APPS =
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
index d054de4d6fc1..cc37c440f650 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
@@ -26,7 +26,6 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
-import android.testing.AndroidTestingRunner
import android.view.Display.DEFAULT_DISPLAY
import android.view.IWindowManager
import android.view.WindowManager.TRANSIT_CHANGE
@@ -43,6 +42,8 @@ import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
import com.android.wm.shell.transition.Transitions
import com.google.common.truth.Truth.assertThat
+import com.google.testing.junit.testparameterinjector.TestParameter
+import com.google.testing.junit.testparameterinjector.TestParameterInjector
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -62,7 +63,7 @@ import org.mockito.kotlin.whenever
* Usage: atest WMShellUnitTests:DesktopDisplayModeControllerTest
*/
@SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(TestParameterInjector::class)
class DesktopDisplayModeControllerTest : ShellTestCase() {
private val transitions = mock<Transitions>()
private val rootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>()
@@ -143,41 +144,24 @@ class DesktopDisplayModeControllerTest : ShellTestCase() {
@Test
@DisableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
- fun displayWindowingModeSwitchOnDisplayConnected_fullscreenDisplay_flagDisabled() {
- testDisplayWindowingModeSwitch(
- defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
- extendedDisplayEnabled = true,
- expectToSwitch = false,
- )
- }
-
- @Test
- @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
- fun displayWindowingModeSwitchOnDisplayConnected_extendedDisplayDisabled() {
+ fun displayWindowingModeSwitchOnDisplayConnected_flagDisabled(
+ @TestParameter param: ModeSwitchTestCase
+ ) {
testDisplayWindowingModeSwitch(
- defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
- extendedDisplayEnabled = false,
+ param.defaultWindowingMode,
+ param.extendedDisplayEnabled,
+ // When the flag is disabled, never switch.
expectToSwitch = false,
)
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
- fun displayWindowingModeSwitchOnDisplayConnected_fullscreenDisplay() {
+ fun displayWindowingModeSwitchOnDisplayConnected(@TestParameter param: ModeSwitchTestCase) {
testDisplayWindowingModeSwitch(
- defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
- extendedDisplayEnabled = true,
- expectToSwitch = true,
- )
- }
-
- @Test
- @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
- fun displayWindowingModeSwitchOnDisplayConnected_freeformDisplay() {
- testDisplayWindowingModeSwitch(
- defaultWindowingMode = WINDOWING_MODE_FREEFORM,
- extendedDisplayEnabled = true,
- expectToSwitch = false,
+ param.defaultWindowingMode,
+ param.extendedDisplayEnabled,
+ param.expectToSwitchByDefault,
)
}
@@ -249,7 +233,34 @@ class DesktopDisplayModeControllerTest : ShellTestCase() {
}
}
- private companion object {
+ companion object {
const val EXTERNAL_DISPLAY_ID = 100
+
+ enum class ModeSwitchTestCase(
+ val defaultWindowingMode: Int,
+ val extendedDisplayEnabled: Boolean,
+ val expectToSwitchByDefault: Boolean,
+ ) {
+ FULLSCREEN_DISPLAY(
+ defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
+ extendedDisplayEnabled = true,
+ expectToSwitchByDefault = true,
+ ),
+ FULLSCREEN_DISPLAY_MIRRORING(
+ defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
+ extendedDisplayEnabled = false,
+ expectToSwitchByDefault = false,
+ ),
+ FREEFORM_DISPLAY(
+ defaultWindowingMode = WINDOWING_MODE_FREEFORM,
+ extendedDisplayEnabled = true,
+ expectToSwitchByDefault = false,
+ ),
+ FREEFORM_DISPLAY_MIRRORING(
+ defaultWindowingMode = WINDOWING_MODE_FREEFORM,
+ extendedDisplayEnabled = false,
+ expectToSwitchByDefault = false,
+ ),
+ }
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt
index 0d1c57221fb9..3e6f688e6acc 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMinimizationTransitionHandlerTest.kt
@@ -33,6 +33,7 @@ import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.transition.Transitions
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
@@ -154,6 +155,24 @@ class DesktopMinimizationTransitionHandlerTest : ShellTestCase() {
assertTrue("Should animate going to back freeform task close transition", animates)
}
+ @Test
+ fun startAnimation_minimizeTransitionToBackFreeformTask_returnsTrue() {
+ val animates =
+ handler.startAnimation(
+ transition = mock(),
+ info =
+ createTransitionInfo(
+ type = Transitions.TRANSIT_MINIMIZE,
+ task = createTask(WINDOWING_MODE_FREEFORM),
+ ),
+ startTransaction = mock(),
+ finishTransaction = mock(),
+ finishCallback = {},
+ )
+
+ assertTrue("Should animate going to back freeform task minimize transition", animates)
+ }
+
private fun createTransitionInfo(
type: Int = WindowManager.TRANSIT_TO_BACK,
changeMode: Int = WindowManager.TRANSIT_TO_BACK,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
index 50590f021a2a..6b0ee5b7ffd4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
@@ -56,7 +56,7 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskOpening_fullscreenTask_notActiveDesktopTask_noop() {
+ fun onTaskOpening_fullscreenTask_nonActiveDesktopTask_noop() {
val task = createFullscreenTask().apply { isVisible = true }
whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
@@ -68,7 +68,7 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskOpening_freeformTask_activeDesktopTask_removesTaskFromRepo() {
+ fun onTaskOpening_fullscreenTask_taskIsActiveInDesktopRepo_removesTaskFromDesktopRepo() {
val task = createFullscreenTask().apply { isVisible = true }
whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
@@ -78,19 +78,20 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskOpening_freeformTask_visibleDesktopTask_addsTaskToRepository() {
+ fun onTaskOpening_freeformTask_activeInDesktopRepository_noop() {
val task = createFreeformTask().apply { isVisible = true }
- whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
desktopTaskChangeListener.onTaskOpening(task)
- verify(desktopUserRepositories.current).addTask(task.displayId, task.taskId, task.isVisible)
+ verify(desktopUserRepositories.current, never())
+ .addTask(task.displayId, task.taskId, task.isVisible)
}
@Test
- fun onTaskOpening_freeformTask_nonVisibleDesktopTask_addsTaskToRepository() {
+ fun onTaskOpening_freeformTask_notActiveInDesktopRepo_addsTaskToRepository() {
val task = createFreeformTask().apply { isVisible = false }
- whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
desktopTaskChangeListener.onTaskOpening(task)
@@ -98,7 +99,7 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskChanging_freeformTaskOutsideDesktop_removesTaskFromRepo() {
+ fun onTaskChanging_fullscreenTask_activeInDesktopRepository_removesTaskFromRepo() {
val task = createFullscreenTask().apply { isVisible = true }
whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
@@ -108,7 +109,27 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskChanging_visibleTaskInDesktop_updatesTaskVisibility() {
+ fun onTaskChanging_fullscreenTask_nonActiveInDesktopRepo_noop() {
+ val task = createFullscreenTask().apply { isVisible = true }
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
+
+ desktopTaskChangeListener.onTaskChanging(task)
+
+ verify(desktopUserRepositories.current, never()).removeTask(task.displayId, task.taskId)
+ }
+
+ @Test
+ fun onTaskChanging_freeformTask_nonActiveTaskInDesktopRepo_addsTaskToDesktopRepo() {
+ val task = createFreeformTask().apply { isVisible = true }
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
+
+ desktopTaskChangeListener.onTaskChanging(task)
+
+ verify(desktopUserRepositories.current).addTask(task.displayId, task.taskId, task.isVisible)
+ }
+
+ @Test
+ fun onTaskChanging_freeformTask_activeVisibleTaskInDesktopRepo_updatesTaskVisibility() {
val task = createFreeformTask().apply { isVisible = true }
whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
@@ -119,7 +140,7 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskChanging_nonVisibleTask_updatesTaskVisibility() {
+ fun onTaskChanging_freeformTask_activeNonVisibleTask_updatesTaskVisibility() {
val task = createFreeformTask().apply { isVisible = false }
whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
@@ -130,7 +151,7 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskMovingToFront_freeformTaskOutsideDesktop_removesTaskFromRepo() {
+ fun onTaskMovingToFront_fullscreenTask_activeTaskInDesktopRepo_removesTaskFromRepo() {
val task = createFullscreenTask().apply { isVisible = true }
whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
@@ -140,9 +161,18 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
}
@Test
- fun onTaskMovingToFront_freeformTaskOutsideDesktop_addsTaskToRepo() {
+ fun onTaskMovingToFront_fullscreenTask_nonActiveTaskInDesktopRepo_noop() {
val task = createFullscreenTask().apply { isVisible = true }
- whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
+ whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
+
+ desktopTaskChangeListener.onTaskMovingToFront(task)
+
+ verify(desktopUserRepositories.current, never()).removeTask(task.displayId, task.taskId)
+ }
+
+ @Test
+ fun onTaskMovingToFront_freeformTask_addsTaskToRepo() {
+ val task = createFreeformTask().apply { isVisible = true }
desktopTaskChangeListener.onTaskMovingToFront(task)
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 d5c84bafbd81..63bf6841dba4 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
@@ -334,6 +334,16 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
whenever(enterDesktopTransitionHandler.moveToDesktop(any(), any())).thenAnswer { Binder() }
whenever(exitDesktopTransitionHandler.startTransition(any(), any(), any(), any()))
.thenReturn(Binder())
+ whenever(
+ desktopMixedTransitionHandler.startLaunchTransition(
+ any(),
+ any(),
+ anyOrNull(),
+ anyOrNull(),
+ anyOrNull(),
+ )
+ )
+ .thenReturn(Binder())
whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
whenever(displayController.getDisplayContext(anyInt())).thenReturn(mockDisplayContext)
whenever(displayController.getDisplay(anyInt())).thenReturn(display)
@@ -1104,44 +1114,44 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
- fun addMoveToDesktopChanges_gravityLeft_noBoundsApplied() {
+ fun addMoveToDeskTaskChanges_gravityLeft_noBoundsApplied() {
setUpLandscapeDisplay()
val task = setUpFullscreenTask(gravity = Gravity.LEFT)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(finalBounds).isEqualTo(Rect())
}
@Test
- fun addMoveToDesktopChanges_gravityRight_noBoundsApplied() {
+ fun addMoveToDeskTaskChanges_gravityRight_noBoundsApplied() {
setUpLandscapeDisplay()
val task = setUpFullscreenTask(gravity = Gravity.RIGHT)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(finalBounds).isEqualTo(Rect())
}
@Test
- fun addMoveToDesktopChanges_gravityTop_noBoundsApplied() {
+ fun addMoveToDeskTaskChanges_gravityTop_noBoundsApplied() {
setUpLandscapeDisplay()
val task = setUpFullscreenTask(gravity = Gravity.TOP)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(finalBounds).isEqualTo(Rect())
}
@Test
- fun addMoveToDesktopChanges_gravityBottom_noBoundsApplied() {
+ fun addMoveToDeskTaskChanges_gravityBottom_noBoundsApplied() {
setUpLandscapeDisplay()
val task = setUpFullscreenTask(gravity = Gravity.BOTTOM)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(finalBounds).isEqualTo(Rect())
@@ -1182,7 +1192,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_positionBottomRight() {
+ fun addMoveToDeskTaskChanges_positionBottomRight() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1191,7 +1201,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1200,7 +1210,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_positionTopLeft() {
+ fun addMoveToDeskTaskChanges_positionTopLeft() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1209,7 +1219,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1218,7 +1228,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_positionBottomLeft() {
+ fun addMoveToDeskTaskChanges_positionBottomLeft() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1227,7 +1237,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1236,7 +1246,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_positionTopRight() {
+ fun addMoveToDeskTaskChanges_positionTopRight() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1245,7 +1255,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1254,7 +1264,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_positionResetsToCenter() {
+ fun addMoveToDeskTaskChanges_positionResetsToCenter() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1263,7 +1273,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1272,7 +1282,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_lastWindowSnapLeft_positionResetsToCenter() {
+ fun addMoveToDeskTaskChanges_lastWindowSnapLeft_positionResetsToCenter() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1284,7 +1294,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1293,7 +1303,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_lastWindowSnapRight_positionResetsToCenter() {
+ fun addMoveToDeskTaskChanges_lastWindowSnapRight_positionResetsToCenter() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1311,7 +1321,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1320,7 +1330,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_lastWindowMaximised_positionResetsToCenter() {
+ fun addMoveToDeskTaskChanges_lastWindowMaximised_positionResetsToCenter() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1330,7 +1340,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1339,7 +1349,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
- fun addMoveToDesktopChanges_defaultToCenterIfFree() {
+ fun addMoveToDeskTaskChanges_defaultToCenterIfFree() {
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1357,7 +1367,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFullscreenTask()
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!))
@@ -1365,7 +1375,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
- fun addMoveToDesktopChanges_excludeCaptionFromAppBounds_nonResizableLandscape() {
+ fun addMoveToDeskTaskChanges_excludeCaptionFromAppBounds_nonResizableLandscape() {
setUpLandscapeDisplay()
val task =
setUpFullscreenTask(
@@ -1375,7 +1385,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
whenever(desktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(task)).thenReturn(true)
val initialAspectRatio = calculateAspectRatio(task)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
val captionInsets = getAppHeaderHeight(context)
@@ -1387,7 +1397,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
- fun addMoveToDesktopChanges_excludeCaptionFromAppBounds_nonResizablePortrait() {
+ fun addMoveToDeskTaskChanges_excludeCaptionFromAppBounds_nonResizablePortrait() {
setUpLandscapeDisplay()
val task =
setUpFullscreenTask(
@@ -1397,7 +1407,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
whenever(desktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(task)).thenReturn(true)
val initialAspectRatio = calculateAspectRatio(task)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
val finalBounds = findBoundsChange(wct, task)
val captionInsets = getAppHeaderHeight(context)
@@ -1435,29 +1445,29 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
- fun addMoveToDesktopChanges_landscapeDevice_userFullscreenOverride_defaultPortraitBounds() {
+ fun addMoveToDeskTaskChanges_landscapeDevice_userFullscreenOverride_defaultPortraitBounds() {
setUpLandscapeDisplay()
val task = setUpFullscreenTask(enableUserFullscreenOverride = true)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_LANDSCAPE_BOUNDS)
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
- fun addMoveToDesktopChanges_landscapeDevice_systemFullscreenOverride_defaultPortraitBounds() {
+ fun addMoveToDeskTaskChanges_landscapeDevice_systemFullscreenOverride_defaultPortraitBounds() {
setUpLandscapeDisplay()
val task = setUpFullscreenTask(enableSystemFullscreenOverride = true)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_LANDSCAPE_BOUNDS)
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
- fun addMoveToDesktopChanges_landscapeDevice_portraitResizableApp_aspectRatioOverridden() {
+ fun addMoveToDeskTaskChanges_landscapeDevice_portraitResizableApp_aspectRatioOverridden() {
setUpLandscapeDisplay()
val task =
setUpFullscreenTask(
@@ -1466,36 +1476,36 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
aspectRatioOverrideApplied = true,
)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_PORTRAIT_BOUNDS)
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
- fun addMoveToDesktopChanges_portraitDevice_userFullscreenOverride_defaultPortraitBounds() {
+ fun addMoveToDeskTaskChanges_portraitDevice_userFullscreenOverride_defaultPortraitBounds() {
setUpPortraitDisplay()
val task = setUpFullscreenTask(enableUserFullscreenOverride = true)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_PORTRAIT_BOUNDS)
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
- fun addMoveToDesktopChanges_portraitDevice_systemFullscreenOverride_defaultPortraitBounds() {
+ fun addMoveToDeskTaskChanges_portraitDevice_systemFullscreenOverride_defaultPortraitBounds() {
setUpPortraitDisplay()
val task = setUpFullscreenTask(enableSystemFullscreenOverride = true)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_PORTRAIT_BOUNDS)
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
- fun addMoveToDesktopChanges_portraitDevice_landscapeResizableApp_aspectRatioOverridden() {
+ fun addMoveToDeskTaskChanges_portraitDevice_landscapeResizableApp_aspectRatioOverridden() {
setUpPortraitDisplay()
val task =
setUpFullscreenTask(
@@ -1505,7 +1515,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
aspectRatioOverrideApplied = true,
)
val wct = WindowContainerTransaction()
- controller.addMoveToDesktopChanges(wct, task)
+ controller.addMoveToDeskTaskChanges(wct, task, deskId = 0)
assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_LANDSCAPE_BOUNDS)
}
@@ -2814,7 +2824,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
fun moveToNextDisplay_toDesktopInOtherDisplay_bringsExistingTasksToFront() {
val transition = Binder()
val sourceDeskId = 0
@@ -2846,7 +2855,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
Flags.FLAG_ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY,
Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
)
- @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
fun moveToNextDisplay_toDesktopInOtherDisplay_movesHomeAndWallpaperToFront() {
val homeTask = setUpHomeTask(displayId = SECOND_DISPLAY)
whenever(desktopWallpaperActivityTokenProvider.getToken(SECOND_DISPLAY))
@@ -3496,6 +3504,39 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ fun handleRequest_fullscreenTask_switchToDesktop_movesTaskToDesk() {
+ taskRepository.addDesk(displayId = DEFAULT_DISPLAY, deskId = 5)
+ setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 5)
+ taskRepository.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 5)
+
+ val fullscreenTask = createFullscreenTask()
+ val wct = controller.handleRequest(Binder(), createTransition(fullscreenTask))
+
+ assertNotNull(wct, "should handle request")
+ verify(desksOrganizer).moveTaskToDesk(wct = wct, deskId = 5, task = fullscreenTask)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ fun handleRequest_fullscreenTaskThatWasInactiveInDesk_tracksDeskDeactivation() {
+ // Set up and existing desktop task in an active desk.
+ val inactiveInDeskTask = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 0)
+ taskRepository.setDeskInactive(deskId = 0)
+
+ // Now the task is launching as fullscreen.
+ inactiveInDeskTask.configuration.windowConfiguration.windowingMode =
+ WINDOWING_MODE_FULLSCREEN
+ val transition = Binder()
+ val wct = controller.handleRequest(transition, createTransition(inactiveInDeskTask))
+
+ // Desk is deactivated.
+ assertNotNull(wct, "should handle request")
+ verify(desksTransitionsObserver)
+ .addPendingTransition(DeskTransition.DeactivateDesk(transition, deskId = 0))
+ }
+
+ @Test
fun handleRequest_fullscreenTask_freeformVisible_returnSwitchToFreeformWCT() {
val homeTask = setUpHomeTask()
val freeformTask = setUpFreeformTask()
@@ -3671,6 +3712,20 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ fun handleRequest_freeformTaskFromInactiveDesk_tracksDeskDeactivation() {
+ val deskId = 0
+ val freeformTask = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = deskId)
+ taskRepository.setDeskInactive(deskId = deskId)
+
+ val transition = Binder()
+ controller.handleRequest(transition, createTransition(freeformTask))
+
+ verify(desksTransitionsObserver)
+ .addPendingTransition(DeskTransition.DeactivateDesk(transition, deskId))
+ }
+
+ @Test
fun handleRequest_freeformTask_relaunchActiveTask_taskBecomesUndefined() {
val freeformTask = setUpFreeformTask()
markTaskHidden(freeformTask)
@@ -3918,6 +3973,24 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
+ fun handleRequest_recentsAnimationRunning_relaunchActiveTask_tracksDeskDeactivation() {
+ // Set up a visible freeform task
+ val freeformTask = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 0)
+ markTaskVisible(freeformTask)
+
+ // Mark recents animation running
+ recentsTransitionStateListener.onTransitionStateChanged(TRANSITION_STATE_ANIMATING)
+
+ val transition = Binder()
+ controller.handleRequest(transition, createTransition(freeformTask))
+
+ desksTransitionsObserver.addPendingTransition(
+ DeskTransition.DeactivateDesk(transition, deskId = 0)
+ )
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
fun handleRequest_topActivityTransparentWithoutDisplay_returnSwitchToFreeformWCT() {
val freeformTask = setUpFreeformTask()
@@ -4035,6 +4108,31 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
}
@Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
+ )
+ fun handleRequest_systemUIActivityWithDisplayInFreeformTask_inDesktop_tracksDeskDeactivation() {
+ val deskId = 5
+ taskRepository.addDesk(displayId = DEFAULT_DISPLAY, deskId = deskId)
+ taskRepository.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = deskId)
+ val systemUIPackageName =
+ context.resources.getString(com.android.internal.R.string.config_systemUi)
+ val baseComponent = ComponentName(systemUIPackageName, /* cls= */ "")
+ val task =
+ setUpFreeformTask(displayId = DEFAULT_DISPLAY).apply {
+ baseActivity = baseComponent
+ isTopActivityNoDisplay = false
+ }
+
+ val transition = Binder()
+ controller.handleRequest(transition, createTransition(task))
+
+ verify(desksTransitionsObserver)
+ .addPendingTransition(DeskTransition.DeactivateDesk(transition, deskId))
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
fun handleRequest_systemUIActivityWithoutDisplay_returnSwitchToFreeformWCT() {
val freeformTask = setUpFreeformTask()
@@ -6576,6 +6674,25 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@EnableFlags(
Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
+ )
+ fun startLaunchTransition_desktopNotShowing_updatesDesktopEnterExitListener() {
+ setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = 0)
+ taskRepository.setDeskInactive(deskId = 0)
+
+ controller.startLaunchTransition(
+ transitionType = TRANSIT_OPEN,
+ wct = WindowContainerTransaction(),
+ launchingTaskId = null,
+ )
+
+ verify(desktopModeEnterExitTransitionListener).onEnterDesktopModeTransitionStarted(any())
+ }
+
+ @Test
+ @EnableFlags(
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
)
fun startLaunchTransition_desktopShowing_doesNotReorderWallpaper() {
val wct = WindowContainerTransaction()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/OWNERS b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/OWNERS
index 736d4cff6ce8..a7d1890a0286 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/OWNERS
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/OWNERS
@@ -1,3 +1,2 @@
# WM shell sub-module TV pip owners
-galinap@google.com
-bronger@google.com \ No newline at end of file
+bronger@google.com
diff --git a/libs/hwui/OWNERS b/libs/hwui/OWNERS
index 70d13ab8b3e5..9c06fd5f0225 100644
--- a/libs/hwui/OWNERS
+++ b/libs/hwui/OWNERS
@@ -3,7 +3,7 @@
alecmouri@google.com
djsollen@google.com
jreck@google.com
-njawad@google.com
+nscobie@google.com
sumir@google.com
# For text, e.g. Typeface, Font, Minikin, etc.
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index fb89973bcc11..66de8c791fdd 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -27,8 +27,6 @@ import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.util.Log;
-import com.android.internal.annotations.KeepForWeakReference;
-
import java.util.concurrent.TimeUnit;
/**
@@ -94,7 +92,6 @@ public class GpsNetInitiatedHandler {
// The internal implementation of TelephonyManager uses WeakReference so we have to keep a
// reference here.
- @KeepForWeakReference
private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener();
private final EmergencyCallCallback mEmergencyCallCallback;
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 9bb31d0076c9..4e86eacea404 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1223,8 +1223,14 @@ public final class MediaCodecInfo {
private static final String TAG = "CodecCapabilities";
// NEW-STYLE CAPABILITIES
+ // Capabilities for an audio codec.
+ @Nullable
private AudioCapabilities mAudioCaps;
+ // Capabilities for a video codec.
+ @Nullable
private VideoCapabilities mVideoCaps;
+ // Capabilities specific to an encoder (vs. a decoder).
+ @Nullable
private EncoderCapabilities mEncoderCaps;
private MediaFormat mDefaultFormat;
@@ -1262,6 +1268,7 @@ public final class MediaCodecInfo {
/**
* Returns the audio capabilities or {@code null} if this is not an audio codec.
*/
+ @Nullable
public AudioCapabilities getAudioCapabilities() {
return mAudioCaps;
}
@@ -1273,6 +1280,7 @@ public final class MediaCodecInfo {
/**
* Returns the encoding capabilities or {@code null} if this is not an encoder.
*/
+ @Nullable
public EncoderCapabilities getEncoderCapabilities() {
return mEncoderCaps;
}
@@ -1284,6 +1292,7 @@ public final class MediaCodecInfo {
/**
* Returns the video capabilities or {@code null} if this is not a video codec.
*/
+ @Nullable
public VideoCapabilities getVideoCapabilities() {
return mVideoCaps;
}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index b11a81047bf8..4e1d472688ea 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -375,6 +375,9 @@ public final class MediaExtractor {
/**
* Extract DRM initialization data if it exists
*
+ * <p>If the media contains a PSSH box, only PSSH version 0 is supported. The result for media
+ * with other PSSH versions is undefined.
+ *
* @return DRM initialization data in the content, or {@code null}
* if no recognizable DRM format is found;
* @see DrmInitData
@@ -460,6 +463,10 @@ public final class MediaExtractor {
/**
* Get the PSSH info if present.
+ *
+ * <p>This method only supports version 0 PSSH boxes. The result for other versions is
+ * undefined.
+ *
* @return a map of uuid-to-bytes, with the uuid specifying
* the crypto scheme, and the bytes being the data specific to that scheme.
* This can be {@code null} if the source does not contain PSSH info.
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index d6e27b0ffa75..9db527bfaa2d 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -18,6 +18,8 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.TestApi;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@@ -61,16 +63,30 @@ import java.util.concurrent.Executor;
*
* @hide
*/
+@TestApi
+@SuppressLint({"UnflaggedApi", "StaticUtils"}) // Test API
public class Utils {
private static final String TAG = "Utils";
+ /** @hide
+ * The vibration uri key parameter
+ */
+ @TestApi
+ @SuppressLint("UnflaggedApi") // Test API
public static final String VIBRATION_URI_PARAM = "vibration_uri";
+ /** @hide
+ * Indicates the synchronized vibration
+ */
+ @TestApi
+ @SuppressLint("UnflaggedApi") // Test API
public static final String SYNCHRONIZED_VIBRATION = "synchronized";
/**
* Sorts distinct (non-intersecting) range array in ascending order.
* @throws java.lang.IllegalArgumentException if ranges are not distinct
+ *
+ * @hide
*/
public static <T extends Comparable<? super T>> void sortDistinctRanges(Range<T>[] ranges) {
Arrays.sort(ranges, new Comparator<Range<T>>() {
@@ -92,6 +108,8 @@ public class Utils {
* @param one a sorted set of non-intersecting ranges in ascending order
* @param another another sorted set of non-intersecting ranges in ascending order
* @return the intersection of the two sets, sorted in ascending order
+ *
+ * @hide
*/
public static <T extends Comparable<? super T>>
Range<T>[] intersectSortedDistinctRanges(Range<T>[] one, Range<T>[] another) {
@@ -124,6 +142,8 @@ public class Utils {
* @return if the value is in one of the ranges, it returns the index of that range. Otherwise,
* the return value is {@code (-1-index)} for the {@code index} of the range that is
* immediately following {@code value}.
+ *
+ * @hide
*/
public static <T extends Comparable<? super T>>
int binarySearchDistinctRanges(Range<T>[] ranges, T value) {
@@ -358,6 +378,8 @@ public class Utils {
* @param fileName desired name for the file.
* @param mimeType MIME type of the file to create.
* @return the File object in the storage, or null if an error occurs.
+ *
+ * @hide
*/
public static File getUniqueExternalFile(Context context, String subdirectory, String fileName,
String mimeType) {
@@ -676,6 +698,8 @@ public class Utils {
* Must match the implementation of BluetoothUtils.toAnonymizedAddress()
* @param address MAC address to be anonymized
* @return anonymized MAC address
+ *
+ * @hide
*/
public static @Nullable String anonymizeBluetoothAddress(@Nullable String address) {
if (address == null) {
@@ -693,6 +717,8 @@ public class Utils {
* @param deviceType the internal type of the audio device
* @param address MAC address to be anonymized
* @return anonymized MAC address
+ *
+ * @hide
*/
public static @Nullable String anonymizeBluetoothAddress(
int deviceType, @Nullable String address) {
@@ -707,6 +733,8 @@ public class Utils {
*
* @param context the {@link Context}
* @return {@code true} if the device supports ringtone vibration
+ *
+ * @hide
*/
public static boolean isRingtoneVibrationSettingsSupported(Context context) {
final Resources res = context.getResources();
@@ -719,6 +747,8 @@ public class Utils {
*
* @param ringtoneUri the ringtone Uri
* @return {@code true} if the Uri has vibration parameter
+ *
+ * @hide
*/
public static boolean hasVibration(Uri ringtoneUri) {
if (ringtoneUri == null) {
@@ -734,6 +764,8 @@ public class Utils {
* @param ringtoneUri the ringtone Uri
* @return parsed {@link Uri} of vibration parameter, {@code null} if the vibration parameter
* is not found.
+ *
+ * @hide
*/
public static @Nullable Uri getVibrationUri(Uri ringtoneUri) {
if (ringtoneUri == null) {
@@ -751,6 +783,8 @@ public class Utils {
*
* @param vibrator the vibrator to resolve the vibration file
* @param vibrationUri the vibration file Uri to represent a vibration
+ *
+ * @hide
*/
@SuppressWarnings("FlaggedApi") // VibrationXmlParser is available internally as hidden APIs.
public static VibrationEffect parseVibrationEffect(Vibrator vibrator, Uri vibrationUri) {
diff --git a/media/jni/OWNERS b/media/jni/OWNERS
index fdddf13a0a23..84618a35cd4f 100644
--- a/media/jni/OWNERS
+++ b/media/jni/OWNERS
@@ -1,5 +1,5 @@
# extra for MTP related files
-per-file android_mtp_*.cpp=aprasath@google.com,anothermark@google.com,kumarashishg@google.com,sarup@google.com,jsharkey@android.com,jameswei@google.com,rmojumder@google.com
+per-file android_mtp_*.cpp=aprasath@google.com,anothermark@google.com,sarup@google.com,jsharkey@android.com,jameswei@google.com,rmojumder@google.com
# extra for TV related files
per-file android_media_tv_*=hgchen@google.com,quxiangfang@google.com
diff --git a/native/webview/TEST_MAPPING b/native/webview/TEST_MAPPING
index 38580595dc2d..c9b54760491a 100644
--- a/native/webview/TEST_MAPPING
+++ b/native/webview/TEST_MAPPING
@@ -17,15 +17,6 @@
"exclude-annotation": "android.test.FlakyTest"
}
]
- },
- {
- "name": "GtsWebViewHostTestCases",
- "keywords": ["internal"],
- "options": [
- {
- "exclude-annotation": "android.test.FlakyTest"
- }
- ]
}
]
}
diff --git a/opengl/java/android/opengl/OWNERS b/opengl/java/android/opengl/OWNERS
index e340bc62567a..4ec9e29c48b0 100644
--- a/opengl/java/android/opengl/OWNERS
+++ b/opengl/java/android/opengl/OWNERS
@@ -3,4 +3,3 @@
sumir@google.com
prahladk@google.com
ianelliott@google.com
-lpy@google.com
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
index 6221659388d1..3db0ac653848 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
@@ -41,6 +41,7 @@
android:id="@+id/action_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
+ android:layout_marginStart="@dimen/settingslib_expressive_space_extrasmall4"
android:theme="?android:attr/actionBarTheme"
android:transitionName="shared_element_view"
app:layout_collapseMode="pin"/>
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index 04df308e72a0..7348920dfd3d 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -8,6 +8,7 @@ edgarwang@google.com
evanlaird@google.com
jiannan@google.com
juliacr@google.com
+millchen@google.com
ykhung@google.com
# Exempt resource files (because they are in a flat directory and too hard to manage via OWNERS)
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background.xml
index 9aa0bc39c5d8..0446873126b7 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background.xml
@@ -19,16 +19,12 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp"
- android:bottom="16dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceBright" />
<corners
android:radius="@dimen/settingslib_preference_corner_radius" />
- <padding
- android:bottom="16dp"/>
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom.xml
index 554cba565383..25a936deade5 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom.xml
@@ -19,9 +19,7 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp"
- android:bottom="16dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceBright" />
@@ -30,8 +28,6 @@
android:bottomLeftRadius="@dimen/settingslib_preference_corner_radius"
android:topRightRadius="4dp"
android:bottomRightRadius="@dimen/settingslib_preference_corner_radius" />
- <padding
- android:bottom="16dp"/>
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_highlighted.xml
index c0c08699cc2a..db2800e0ec41 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_highlighted.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_highlighted.xml
@@ -19,8 +19,7 @@
<item
android:bottom="16dp"
android:end="?android:attr/listPreferredItemPaddingEnd"
- android:start="?android:attr/listPreferredItemPaddingStart"
- android:top="2dp">
+ android:start="?android:attr/listPreferredItemPaddingStart">
<shape
android:shape="rectangle"
android:tint="?android:attr/colorAccent">
@@ -29,8 +28,7 @@
android:bottomRightRadius="@dimen/settingslib_preference_corner_radius"
android:topLeftRadius="4dp"
android:topRightRadius="4dp" />
- <padding android:bottom="16dp" />
<solid android:color="#42000000" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_selected.xml
index 543b237373fb..98f95d927fa6 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_selected.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_bottom_selected.xml
@@ -19,9 +19,7 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp"
- android:bottom="16dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceContainer" />
@@ -30,8 +28,6 @@
android:bottomLeftRadius="@dimen/settingslib_preference_corner_radius"
android:topRightRadius="4dp"
android:bottomRightRadius="@dimen/settingslib_preference_corner_radius" />
- <padding
- android:bottom="16dp"/>
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center.xml
index b89a0ddcdec5..c4286fdf020c 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center.xml
@@ -19,8 +19,7 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceBright" />
@@ -28,4 +27,4 @@
android:radius="4dp" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_highlighted.xml
index 8099d9b3d7f7..194cdb00a337 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_highlighted.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_highlighted.xml
@@ -18,8 +18,7 @@
android:color="?android:colorControlHighlight">
<item
android:end="?android:attr/listPreferredItemPaddingEnd"
- android:start="?android:attr/listPreferredItemPaddingStart"
- android:top="2dp">
+ android:start="?android:attr/listPreferredItemPaddingStart">
<shape
android:shape="rectangle"
android:tint="?android:attr/colorAccent">
@@ -27,4 +26,4 @@
<solid android:color="#42000000" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_selected.xml
index 6d2cd1a51620..8bc2f2f9ccd1 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_selected.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_center_selected.xml
@@ -19,8 +19,7 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceContainer" />
@@ -28,4 +27,4 @@
android:radius="4dp" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_highlighted.xml
index a119a4ae083f..2341661528d9 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_highlighted.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_highlighted.xml
@@ -19,14 +19,12 @@
<item
android:bottom="16dp"
android:end="?android:attr/listPreferredItemPaddingEnd"
- android:start="?android:attr/listPreferredItemPaddingStart"
- android:top="2dp">
+ android:start="?android:attr/listPreferredItemPaddingStart">
<shape
android:shape="rectangle"
android:tint="?android:attr/colorAccent">
<corners android:radius="@dimen/settingslib_preference_corner_radius" />
- <padding android:bottom="16dp" />
<solid android:color="#42000000" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_selected.xml
index bcdbf1d19545..99704f2df190 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_selected.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_selected.xml
@@ -19,16 +19,12 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp"
- android:bottom="16dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceContainer" />
<corners
android:radius="@dimen/settingslib_preference_corner_radius" />
- <padding
- android:bottom="16dp"/>
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top.xml
index 7955e4418ae9..3a5938688f34 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top.xml
@@ -19,8 +19,7 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceBright" />
@@ -31,4 +30,4 @@
android:bottomRightRadius="4dp" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_highlighted.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_highlighted.xml
index 052eb01cab8d..edace29df37a 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_highlighted.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_highlighted.xml
@@ -19,8 +19,7 @@
<item
android:color="?android:attr/colorAccent"
android:end="?android:attr/listPreferredItemPaddingEnd"
- android:start="?android:attr/listPreferredItemPaddingStart"
- android:top="2dp">
+ android:start="?android:attr/listPreferredItemPaddingStart">
<shape
android:shape="rectangle"
android:tint="?android:attr/colorAccent">
@@ -32,4 +31,4 @@
<solid android:color="#42000000" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_selected.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_selected.xml
index d4b658c384e6..b2d6d9da6af8 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_selected.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v36/settingslib_round_background_top_selected.xml
@@ -19,8 +19,7 @@
android:color="?android:colorControlHighlight">
<item
android:start="?android:attr/listPreferredItemPaddingStart"
- android:end="?android:attr/listPreferredItemPaddingEnd"
- android:top="2dp">
+ android:end="?android:attr/listPreferredItemPaddingEnd">
<shape android:shape="rectangle">
<solid
android:color="@color/settingslib_materialColorSurfaceContainer" />
@@ -31,4 +30,4 @@
android:bottomRightRadius="4dp" />
</shape>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/NormalPaddingMixin.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/NormalPaddingMixin.kt
new file mode 100644
index 000000000000..5035542b9783
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/NormalPaddingMixin.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.settingslib.widget
+
+/**
+ * A base interface to indicate that a Preference should have normal paddings.
+ *
+ * Preferences implementing this interface will be treated as has normal paddings both inside and
+ * outside.
+ */
+interface NormalPaddingMixin \ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsBasePreferenceFragment.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsBasePreferenceFragment.kt
index 8d12f01e24ed..22cd87307a42 100644
--- a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsBasePreferenceFragment.kt
+++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsBasePreferenceFragment.kt
@@ -16,6 +16,7 @@
package com.android.settingslib.widget
+import android.graphics.Rect
import android.os.Bundle
import android.view.LayoutInflater;
import android.view.View
@@ -24,6 +25,7 @@ import androidx.annotation.CallSuper
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceScreen
import androidx.recyclerview.widget.RecyclerView
+import com.android.settingslib.widget.theme.R
/** Base class for Settings to use PreferenceFragmentCompat */
abstract class SettingsBasePreferenceFragment : PreferenceFragmentCompat() {
@@ -43,6 +45,7 @@ abstract class SettingsBasePreferenceFragment : PreferenceFragmentCompat() {
if (SettingsThemeHelper.isExpressiveTheme(requireContext())) {
// Don't allow any divider in between the preferences in expressive design.
setDivider(null)
+ this.listView.addItemDecoration(MarginItemDecoration())
}
}
@@ -51,4 +54,18 @@ abstract class SettingsBasePreferenceFragment : PreferenceFragmentCompat() {
return SettingsPreferenceGroupAdapter(preferenceScreen)
return super.onCreateAdapter(preferenceScreen)
}
+
+ internal class MarginItemDecoration() : RecyclerView.ItemDecoration() {
+ override fun getItemOffsets(
+ outRect: Rect,
+ view: View,
+ parent: RecyclerView,
+ state: RecyclerView.State,
+ ) {
+ with(outRect) {
+ bottom =
+ view.resources.getDimensionPixelSize(R.dimen.settingslib_expressive_radius_extrasmall1)
+ }
+ }
+ }
}
diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
index a04fce7eeb86..2672787a0519 100644
--- a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
+++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
@@ -177,14 +177,32 @@ open class SettingsPreferenceGroupAdapter(preferenceGroup: PreferenceGroup) :
val v = holder.itemView
// Update padding
if (SettingsThemeHelper.isExpressiveTheme(context)) {
- val paddingStart = if (backgroundRes == 0) mNormalPaddingStart else mGroupPaddingStart
- val paddingEnd = if (backgroundRes == 0) mNormalPaddingEnd else mGroupPaddingEnd
+ val (paddingStart, paddingEnd) = getStartEndPadding(position, backgroundRes)
v.setPaddingRelative(paddingStart, v.paddingTop, paddingEnd, v.paddingBottom)
+ v.clipToOutline = backgroundRes != 0
}
// Update background
v.setBackgroundResource(backgroundRes)
}
+ private fun getStartEndPadding(position: Int, backgroundRes: Int): Pair<Int, Int> {
+ val item = getItem(position)
+ return when {
+ // This item handles edge to edge itself
+ item is NormalPaddingMixin && item is GroupSectionDividerMixin -> 0 to 0
+
+ // According to mappingPreferenceGroup(), backgroundRes == 0 means this item is
+ // GroupSectionDividerMixin or PreferenceCategory, which is design to have normal
+ // padding.
+ // NormalPaddingMixin items are also designed to have normal padding.
+ backgroundRes == 0 || item is NormalPaddingMixin ->
+ mNormalPaddingStart to mNormalPaddingEnd
+
+ // Other items are suppose to have group padding.
+ else -> mGroupPaddingStart to mGroupPaddingEnd
+ }
+ }
+
@DrawableRes
protected fun getRoundCornerDrawableRes(position: Int, isSelected: Boolean): Int {
return getRoundCornerDrawableRes(position, isSelected, false)
diff --git a/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java b/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java
index 4315238ad7c1..fe8e8b6f1d46 100644
--- a/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java
+++ b/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java
@@ -22,6 +22,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
@@ -72,6 +73,7 @@ public class SliderPreference extends Preference {
private int mSliderIncrement;
private boolean mAdjustable;
private boolean mTrackingTouch;
+ private CharSequence mSliderContentDescription;
/**
* Listener reacting to the user pressing DPAD left/right keys if {@code
@@ -143,6 +145,7 @@ public class SliderPreference extends Preference {
@Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setLayoutResource(R.layout.settingslib_expressive_preference_slider);
+ setSelectable(false);
TypedArray a = context.obtainStyledAttributes(
attrs, androidx.preference.R.styleable.SeekBarPreference, defStyleAttr,
@@ -265,6 +268,14 @@ public class SliderPreference extends Preference {
} else {
mSliderIncrement = (int) (mSlider.getStepSize());
}
+ final CharSequence title = getTitle();
+ if (!TextUtils.isEmpty(mSliderContentDescription)) {
+ mSlider.setContentDescription(mSliderContentDescription);
+ } else if (!TextUtils.isEmpty(title)) {
+ mSlider.setContentDescription(title);
+ } else {
+ mSlider.setContentDescription(null);
+ }
mSlider.setValueFrom(mMin);
mSlider.setValueTo(mMax);
mSlider.setValue(mSliderValue);
@@ -273,6 +284,8 @@ public class SliderPreference extends Preference {
mSlider.clearOnChangeListeners();
mSlider.addOnChangeListener(mChangeListener);
mSlider.setEnabled(isEnabled());
+ mSlider.setFocusable(isSelectable());
+ mSlider.setClickable(isSelectable());
// Set up slider color
mSlider.setTrackActiveTintList(mTrackActiveColor);
@@ -471,6 +484,19 @@ public class SliderPreference extends Preference {
setValueInternal(sliderValue, true);
}
+
+ /**
+ * Sets the content description of the {@link Slider}.
+ *
+ * @param contentDescription The content description of the {@link Slider}
+ */
+ public void setSliderContentDescription(@Nullable CharSequence contentDescription) {
+ mSliderContentDescription = contentDescription;
+ if (mSlider != null) {
+ mSlider.setContentDescription(contentDescription);
+ }
+ }
+
@Override
protected void onSetInitialValue(@Nullable Object defaultValue) {
if (defaultValue == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS b/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS
index b9449acc6f7d..50bfe8c7cd78 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS
@@ -1,6 +1,5 @@
# Default reviewers for this and subdirectories.
andychou@google.com
-arcwang@google.com
asapperstein@google.com
changbetty@google.com
qal@google.com
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index c98a741f8254..99c4e21c6053 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -456,11 +456,16 @@ public class SettingsState {
@GuardedBy("mLock")
private void loadAconfigDefaultValuesLocked(List<String> filePaths) {
for (String fileName : filePaths) {
- try (FileInputStream inputStream = new FileInputStream(fileName)) {
- loadAconfigDefaultValues(
- inputStream.readAllBytes(), mNamespaceDefaults, mAconfigDefaultFlags);
- } catch (IOException e) {
- Slog.e(LOG_TAG, "failed to read protobuf", e);
+ File f = new File(fileName);
+ if (f.isFile() && f.canRead()) {
+ try (FileInputStream inputStream = new FileInputStream(fileName)) {
+ loadAconfigDefaultValues(
+ inputStream.readAllBytes(), mNamespaceDefaults, mAconfigDefaultFlags);
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "failed to read protobuf", e);
+ }
+ } else {
+ Slog.d(LOG_TAG, "No protobuf file at " + fileName);
}
}
}
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
index 576afdc824f2..897c1fe7639e 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -4,12 +4,9 @@ ronish@google.com
jsharkey@android.com
felipeal@google.com
nandana@google.com
-svetoslavganov@google.com
hackbod@google.com
yamasani@google.com
-toddke@google.com
patb@google.com
-cbrubaker@google.com
omakoto@google.com
michaelwr@google.com
ronish@google.com
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
index 2c6d09a4593a..2d03e2bcdd19 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
@@ -23,7 +23,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntRect
@@ -35,7 +34,6 @@ import com.android.systemui.communal.smartspace.SmartspaceInteractionHandler
import com.android.systemui.communal.ui.compose.section.AmbientStatusBarSection
import com.android.systemui.communal.ui.compose.section.CommunalLockSection
import com.android.systemui.communal.ui.compose.section.CommunalPopupSection
-import com.android.systemui.communal.ui.compose.section.CommunalToDreamButtonSection
import com.android.systemui.communal.ui.compose.section.HubOnboardingSection
import com.android.systemui.communal.ui.view.layout.sections.CommunalAppWidgetSection
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
@@ -61,7 +59,6 @@ constructor(
private val ambientStatusBarSection: AmbientStatusBarSection,
private val communalPopupSection: CommunalPopupSection,
private val widgetSection: CommunalAppWidgetSection,
- private val communalToDreamButtonSection: CommunalToDreamButtonSection,
private val hubOnboardingSection: HubOnboardingSection,
) {
@@ -103,13 +100,11 @@ constructor(
Modifier.element(Communal.Elements.IndicationArea).fillMaxWidth()
)
}
- with(communalToDreamButtonSection) { Button() }
},
) { measurables, constraints ->
val communalGridMeasurable = measurables[0]
val lockIconMeasurable = measurables[1]
val bottomAreaMeasurable = measurables[2]
- val screensaverButtonMeasurable: Measurable? = measurables.getOrNull(3)
val noMinConstraints = constraints.copy(minWidth = 0, minHeight = 0)
@@ -152,9 +147,6 @@ constructor(
val bottomAreaPlaceable = bottomAreaMeasurable.measure(noMinConstraints)
- val screensaverButtonPlaceable =
- screensaverButtonMeasurable?.measure(noMinConstraints)
-
val communalGridPlaceable =
communalGridMeasurable.measure(
noMinConstraints.copy(maxHeight = lockIconBounds.top)
@@ -166,26 +158,12 @@ constructor(
val bottomAreaTop = constraints.maxHeight - bottomAreaPlaceable.height
bottomAreaPlaceable.place(x = 0, y = bottomAreaTop)
-
- val screensaverButtonPaddingInt = screensaverButtonPadding.roundToPx()
- screensaverButtonPlaceable?.place(
- x =
- constraints.maxWidth -
- screensaverButtonPaddingInt -
- screensaverButtonPlaceable.width,
- y =
- constraints.maxHeight -
- screensaverButtonPaddingInt -
- screensaverButtonPlaceable.height,
- )
}
}
}
}
companion object {
- private val screensaverButtonPadding: Dp = 24.dp
-
// TODO(b/382739998): Remove these hardcoded values once lock icon size and bottom area
// position are sorted.
private val lockIconSize: Dp = 54.dp
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt
deleted file mode 100644
index acaf43a62f43..000000000000
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt
+++ /dev/null
@@ -1,231 +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.communal.ui.compose.section
-
-import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.core.MutableTransitionState
-import androidx.compose.animation.expandVertically
-import androidx.compose.animation.fadeIn
-import androidx.compose.animation.fadeOut
-import androidx.compose.animation.shrinkVertically
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.widthIn
-import androidx.compose.foundation.shape.CornerSize
-import androidx.compose.material3.IconButtonDefaults
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Surface
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.CornerRadius
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.RoundRect
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.geometry.toRect
-import androidx.compose.ui.graphics.Outline
-import androidx.compose.ui.graphics.Path
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.res.dimensionResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.dp
-import com.android.compose.PlatformIconButton
-import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
-import com.android.systemui.communal.ui.compose.extensions.observeTaps
-import com.android.systemui.communal.ui.viewmodel.CommunalToDreamButtonViewModel
-import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.res.R
-import javax.inject.Inject
-import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.delay
-
-class CommunalToDreamButtonSection
-@Inject
-constructor(
- private val communalSettingsInteractor: CommunalSettingsInteractor,
- private val viewModelFactory: CommunalToDreamButtonViewModel.Factory,
-) {
- @Composable
- fun Button() {
- if (!communalSettingsInteractor.isV2FlagEnabled()) {
- return
- }
-
- val viewModel =
- rememberViewModel("CommunalToDreamButtonSection") { viewModelFactory.create() }
-
- if (!viewModel.shouldShowDreamButtonOnHub) {
- return
- }
-
- val buttonSize = dimensionResource(R.dimen.communal_to_dream_button_size)
-
- if (viewModel.shouldShowTooltip) {
- val tooltipVisibleState = remember { MutableTransitionState(false) }
-
- Column(
- modifier =
- Modifier.widthIn(max = tooltipMaxWidth).pointerInput(Unit) {
- observeTaps {
- if (tooltipVisibleState.isCurrentlyVisible()) {
- tooltipVisibleState.targetState = false
- }
- }
- }
- ) {
- var waitingToShowTooltip by remember { mutableStateOf(true) }
-
- LaunchedEffect(tooltipVisibleState.targetState) {
- delay(3.seconds)
- tooltipVisibleState.targetState = true
- waitingToShowTooltip = false
- }
-
- // This LaunchedEffect is used to wait for the tooltip dismiss animation to
- // complete before setting the tooltip dismissed. Otherwise, the composable would
- // be removed before the animation can start.
- LaunchedEffect(
- tooltipVisibleState.currentState,
- tooltipVisibleState.isIdle,
- waitingToShowTooltip,
- ) {
- if (
- !waitingToShowTooltip &&
- !tooltipVisibleState.currentState &&
- tooltipVisibleState.isIdle
- ) {
- viewModel.setDreamButtonTooltipDismissed()
- }
- }
-
- AnimatedVisibility(
- visibleState = tooltipVisibleState,
- enter = fadeIn() + expandVertically(expandFrom = Alignment.Bottom),
- exit = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Bottom),
- ) {
- Tooltip(
- pointerOffsetDp = buttonSize.div(2),
- text = stringResource(R.string.glanceable_hub_to_dream_button_tooltip),
- )
- }
-
- GoToDreamButton(
- modifier = Modifier.width(buttonSize).height(buttonSize).align(Alignment.End)
- ) {
- viewModel.onShowDreamButtonTap()
- }
- }
- } else {
- GoToDreamButton(modifier = Modifier.width(buttonSize).height(buttonSize)) {
- viewModel.onShowDreamButtonTap()
- }
- }
- }
-
- private fun MutableTransitionState<Boolean>.isCurrentlyVisible() = currentState && isIdle
-
- companion object {
- private val tooltipMaxWidth = 350.dp
- }
-}
-
-@Composable
-private fun GoToDreamButton(modifier: Modifier, onClick: () -> Unit) {
- PlatformIconButton(
- modifier = modifier,
- onClick = onClick,
- iconResource = R.drawable.ic_screensaver_auto,
- contentDescription = stringResource(R.string.accessibility_glanceable_hub_to_dream_button),
- colors =
- IconButtonDefaults.filledIconButtonColors(
- contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
- containerColor = MaterialTheme.colorScheme.primaryContainer,
- ),
- )
-}
-
-@Composable
-private fun Tooltip(pointerOffsetDp: Dp, text: String) {
- Surface(
- color = MaterialTheme.colorScheme.surface,
- shape = TooltipShape(pointerSizeDp = 12.dp, pointerOffsetDp = pointerOffsetDp),
- ) {
- Text(
- modifier = Modifier.padding(start = 32.dp, top = 16.dp, end = 32.dp, bottom = 32.dp),
- color = MaterialTheme.colorScheme.onSurface,
- text = text,
- )
- }
-
- Spacer(modifier = Modifier.height(4.dp))
-}
-
-private class TooltipShape(private val pointerSizeDp: Dp, private val pointerOffsetDp: Dp) : Shape {
-
- override fun createOutline(
- size: Size,
- layoutDirection: LayoutDirection,
- density: Density,
- ): Outline {
-
- val pointerSizePx = with(density) { pointerSizeDp.toPx() }
- val pointerOffsetPx = with(density) { pointerOffsetDp.toPx() }
- val cornerRadius = CornerRadius(CornerSize(16.dp).toPx(size, density))
- val bubbleSize = size.copy(height = size.height - pointerSizePx)
-
- val path =
- Path().apply {
- addRoundRect(
- RoundRect(
- rect = bubbleSize.toRect(),
- topLeft = cornerRadius,
- topRight = cornerRadius,
- bottomRight = cornerRadius,
- bottomLeft = cornerRadius,
- )
- )
- addPath(
- Path().apply {
- moveTo(0f, 0f)
- lineTo(pointerSizePx / 2f, pointerSizePx)
- lineTo(pointerSizePx, 0f)
- close()
- },
- offset =
- Offset(
- x = bubbleSize.width - pointerOffsetPx - pointerSizePx / 2f,
- y = bubbleSize.height,
- ),
- )
- }
-
- return Outline.Generic(path)
- }
-}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index b59b4ab34c80..06484128ed6c 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -103,6 +103,7 @@ open class ClockRegistry(
fun onAvailableClocksChanged() {}
}
+ private val replacementMap = ConcurrentHashMap<ClockId, ClockId>()
private val availableClocks = ConcurrentHashMap<ClockId, ClockInfo>()
private val clockChangeListeners = mutableListOf<ClockChangeListener>()
private val settingObserver =
@@ -209,6 +210,7 @@ open class ClockRegistry(
continue
}
+ clock.replacementTarget?.let { replacementMap[id] = it }
info.provider = plugin
onLoaded(info)
}
@@ -393,10 +395,11 @@ open class ClockRegistry(
// TODO: Merge w/ CurrentClockId when we convert to a flow. We shouldn't need both behaviors.
val activeClockId: String
get() {
- if (!availableClocks.containsKey(currentClockId)) {
+ var id = currentClockId
+ if (!availableClocks.containsKey(id)) {
return DEFAULT_CLOCK_ID
}
- return currentClockId
+ return replacementMap[id] ?: id
}
init {
@@ -404,6 +407,7 @@ open class ClockRegistry(
defaultClockProvider.initialize(clockBuffers)
for (clock in defaultClockProvider.getClocks()) {
availableClocks[clock.clockId] = ClockInfo(clock, defaultClockProvider, null)
+ clock.replacementTarget?.let { replacementMap[clock.clockId] = it }
}
// Something has gone terribly wrong if the default clock isn't present
@@ -562,9 +566,12 @@ open class ClockRegistry(
}
}
- fun getClocks(): List<ClockMetadata> {
- if (!isEnabled) return listOf(availableClocks[DEFAULT_CLOCK_ID]!!.metadata)
- return availableClocks.map { (_, clock) -> clock.metadata }
+ fun getClocks(includeDeprecated: Boolean = false): List<ClockMetadata> {
+ return when {
+ !isEnabled -> listOf(availableClocks[DEFAULT_CLOCK_ID]!!.metadata)
+ includeDeprecated -> availableClocks.map { (_, clock) -> clock.metadata }
+ else -> availableClocks.map { (_, clock) -> clock.metadata }.filter { !it.isDeprecated }
+ }
}
fun getClockPickerConfig(clockId: ClockId): ClockPickerConfig? {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 654478af3fb0..c3935e68ca04 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -61,7 +61,14 @@ class DefaultClockProvider(
override fun getClocks(): List<ClockMetadata> {
var clocks = listOf(ClockMetadata(DEFAULT_CLOCK_ID))
- if (isClockReactiveVariantsEnabled) clocks += ClockMetadata(FLEX_CLOCK_ID)
+ if (isClockReactiveVariantsEnabled) {
+ clocks +=
+ ClockMetadata(
+ FLEX_CLOCK_ID,
+ isDeprecated = true,
+ replacementTarget = DEFAULT_CLOCK_ID,
+ )
+ }
return clocks
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 189d554415d0..f4d4b1efa3e2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -25,6 +25,8 @@ import android.view.Gravity
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
+import android.view.ViewTreeObserver
+import android.view.ViewTreeObserver.OnPreDrawListener
import android.view.WindowInsetsController
import android.widget.FrameLayout
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -720,6 +722,37 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
}
@Test
+ fun startAppearAnimation_ifDelayed() {
+ val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
+ whenever(view.isAppearAnimationDelayed).thenReturn(true)
+ val viewTreeObserver: ViewTreeObserver = mock()
+ whenever(view.viewTreeObserver).thenReturn(viewTreeObserver)
+
+ underTest.startAppearAnimationIfDelayed()
+
+ verify(view).alpha = 1f
+ verify(viewTreeObserver).addOnPreDrawListener(argumentCaptor.capture())
+ argumentCaptor.value.onPreDraw()
+
+ verify(view).startAppearAnimation(any(SecurityMode::class.java))
+ verify(view).setIsAppearAnimationDelayed(false)
+ }
+
+ @Test
+ fun appearAnimation_willNotStart_ifNotDelayed() {
+ whenever(view.isAppearAnimationDelayed).thenReturn(false)
+ val viewTreeObserver: ViewTreeObserver = mock()
+ whenever(view.viewTreeObserver).thenReturn(viewTreeObserver)
+
+ underTest.startAppearAnimationIfDelayed()
+
+ verify(view, never()).alpha
+ verify(viewTreeObserver, never()).addOnPreDrawListener(any())
+
+ verify(view, never()).startAppearAnimation(any(SecurityMode::class.java))
+ }
+
+ @Test
fun gravityReappliedOnConfigurationChange() {
// Set initial gravity
testableResources.addOverride(R.integer.keyguard_host_view_gravity, Gravity.CENTER)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 176824fd4c5d..2845f6a2983a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -452,6 +452,14 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
verify(keyguardPasswordView).setDisappearAnimationListener(any());
}
+ @Test
+ public void setupForDelayedAppear() {
+ mKeyguardSecurityContainer.setupForDelayedAppear();
+ assertThat(mKeyguardSecurityContainer.getTranslationY()).isEqualTo(0f);
+ assertThat(mKeyguardSecurityContainer.getAlpha()).isEqualTo(0f);
+ assertThat(mKeyguardSecurityContainer.isAppearAnimationDelayed()).isTrue();
+ }
+
private BackEvent createBackEvent(float touchX, float progress) {
return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT);
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java
index f53f964cd3d9..191ecccd5f71 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerFullscreenSwipeTouchHandlerTest.java
@@ -28,6 +28,8 @@ import static org.mockito.Mockito.when;
import android.animation.ValueAnimator;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
@@ -54,6 +56,7 @@ import com.android.systemui.scene.ui.view.WindowRootView;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.Before;
@@ -127,10 +130,16 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
@Mock
WindowRootView mWindowRootView;
+ @Mock
+ Resources mResources;
+
private SceneInteractor mSceneInteractor;
+ private KeyguardStateController mKeyguardStateController;
+
private static final float TOUCH_REGION = .3f;
private static final float MIN_BOUNCER_HEIGHT = .05f;
+ private final Configuration mConfiguration = new Configuration();
private static final Rect SCREEN_BOUNDS = new Rect(0, 0, 1024, 100);
private static final UserInfo CURRENT_USER_INFO = new UserInfo(
@@ -153,6 +162,8 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
public void setup() {
mKosmos = new KosmosJavaAdapter(this);
mSceneInteractor = spy(mKosmos.getSceneInteractor());
+ mKeyguardStateController = mKosmos.getKeyguardStateController();
+ mConfiguration.orientation = Configuration.ORIENTATION_PORTRAIT;
MockitoAnnotations.initMocks(this);
mTouchHandler = new BouncerSwipeTouchHandler(
@@ -172,7 +183,9 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
mKeyguardInteractor,
mSceneInteractor,
mKosmos.getShadeRepository(),
- Optional.of(() -> mWindowRootView));
+ Optional.of(() -> mWindowRootView),
+ mKeyguardStateController,
+ mKosmos.getCommunalSettingsInteractor());
when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
@@ -180,6 +193,9 @@ public class BouncerFullscreenSwipeTouchHandlerTest extends SysuiTestCase {
when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn(Float.MAX_VALUE);
when(mTouchSession.getBounds()).thenReturn(SCREEN_BOUNDS);
when(mKeyguardInteractor.isKeyguardDismissible()).thenReturn(MutableStateFlow(false));
+ when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(true);
+ when(mWindowRootView.getResources()).thenReturn(mResources);
+ when(mResources.getConfiguration()).thenReturn(mConfiguration);
}
/**
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
index dd43d817cccc..e8dc6762cc92 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
@@ -16,6 +16,10 @@
package com.android.systemui.ambient.touch;
+import static android.platform.test.flag.junit.FlagsParameterization.allCombinationsOf;
+
+import static com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2;
+
import static com.google.common.truth.Truth.assertThat;
import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
@@ -34,6 +38,8 @@ import static org.mockito.Mockito.when;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.Region;
import android.platform.test.annotations.DisableFlags;
@@ -63,6 +69,7 @@ import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.Before;
@@ -132,12 +139,16 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
@Mock
WindowRootView mWindowRootView;
+ Resources mResources;
+
@Mock
CommunalViewModel mCommunalViewModel;
@Mock
KeyguardInteractor mKeyguardInteractor;
+ private KeyguardStateController mKeyguardStateController;
+
@Captor
ArgumentCaptor<Rect> mRectCaptor;
@@ -147,6 +158,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
private static final int SCREEN_WIDTH_PX = 1024;
private static final int SCREEN_HEIGHT_PX = 100;
private static final float MIN_BOUNCER_HEIGHT = .05f;
+ private final Configuration mConfiguration = new Configuration();
private static final Rect SCREEN_BOUNDS = new Rect(0, 0, 1024, 100);
private static final UserInfo CURRENT_USER_INFO = new UserInfo(
@@ -157,7 +169,8 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
- return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag();
+ return SceneContainerFlagParameterizationKt
+ .andSceneContainer(allCombinationsOf(Flags.FLAG_GLANCEABLE_HUB_V2));
}
public BouncerSwipeTouchHandlerTest(FlagsParameterization flags) {
@@ -168,7 +181,13 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
@Before
public void setup() {
mKosmos = new KosmosJavaAdapter(this);
+ mContext.ensureTestableResources();
+ mResources = mContext.getResources();
+ overrideConfiguration(mConfiguration);
+ mConfiguration.orientation = Configuration.ORIENTATION_PORTRAIT;
+
mSceneInteractor = spy(mKosmos.getSceneInteractor());
+ mKeyguardStateController = mKosmos.getKeyguardStateController();
MockitoAnnotations.initMocks(this);
mTouchHandler = new BouncerSwipeTouchHandler(
@@ -188,7 +207,9 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
mKeyguardInteractor,
mSceneInteractor,
mKosmos.getShadeRepository(),
- Optional.of(() -> mWindowRootView)
+ Optional.of(() -> mWindowRootView),
+ mKeyguardStateController,
+ mKosmos.getCommunalSettingsInteractor()
);
when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
@@ -197,6 +218,9 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn(Float.MAX_VALUE);
when(mTouchSession.getBounds()).thenReturn(SCREEN_BOUNDS);
when(mKeyguardInteractor.isKeyguardDismissible()).thenReturn(MutableStateFlow(false));
+ when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(true);
+ when(mWindowRootView.getResources()).thenReturn(mResources);
+ setCommunalV2ConfigEnabled(true);
}
/**
@@ -586,6 +610,43 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
}
+ @Test
+ @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ public void swipeUpAboveThresholdInLandscape_keyguardRotationNotAllowed_showsBouncer() {
+ when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
+ mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
+
+ final float swipeUpPercentage = .1f;
+ // The upward velocity is ignored.
+ final float velocityY = -1;
+ swipeToPosition(swipeUpPercentage, velocityY);
+
+ // Ensure show bouncer scrimmed
+ verify(mScrimController).show(true);
+ verify(mValueAnimatorCreator, never()).create(anyFloat(), anyFloat());
+ verify(mValueAnimator, never()).start();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ public void swipeUpBelowThreshold_inLandscapeKeyguardRotationNotAllowed_noBouncer() {
+ mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
+
+ final float swipeUpPercentage = .02f;
+ // The upward velocity is ignored.
+ final float velocityY = -1;
+ swipeToPosition(swipeUpPercentage, velocityY);
+
+ // no bouncer shown scrimmed
+ verify(mScrimController, never()).show(true);
+ // on touch end, bouncer hidden
+ verify(mValueAnimatorCreator).create(eq(1 - swipeUpPercentage),
+ eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
+ verify(mValueAnimator, never()).addListener(any());
+ }
+
/**
* Tests that swiping up with a speed above the set threshold will continue the expansion.
*/
@@ -672,4 +733,15 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
inputEventListenerCaptor.getValue().onInputEvent(upEvent);
}
+
+ private void setCommunalV2ConfigEnabled(boolean enabled) {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_glanceableHubEnabled,
+ enabled);
+ }
+
+ private void overrideConfiguration(Configuration configuration) {
+ mContext.getOrCreateTestableResources().overrideConfiguration(
+ configuration);
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
index 7051f81cfc88..f58391496e65 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
@@ -22,6 +22,7 @@ import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
import com.android.internal.logging.uiEventLoggerFake
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
@@ -38,8 +39,13 @@ import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+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.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.collectLastValue
@@ -56,11 +62,15 @@ import com.google.common.truth.Truth.assertThat
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.advanceTimeBy
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.kotlin.verify
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
@@ -93,10 +103,12 @@ class CommunalSceneStartableTest(flags: FlagsParameterization) : SysuiTestCase()
communalInteractor = communalInteractor,
communalSettingsInteractor = communalSettingsInteractor,
communalSceneInteractor = communalSceneInteractor,
+ keyguardTransitionInteractor = keyguardTransitionInteractor,
keyguardInteractor = keyguardInteractor,
systemSettings = fakeSettings,
notificationShadeWindowController = notificationShadeWindowController,
bgScope = applicationCoroutineScope,
+ applicationScope = applicationCoroutineScope,
mainDispatcher = testDispatcher,
uiEventLogger = uiEventLoggerFake,
)
@@ -111,13 +123,13 @@ class CommunalSceneStartableTest(flags: FlagsParameterization) : SysuiTestCase()
UserHandle.USER_CURRENT,
)
fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
+ setCommunalV2ConfigEnabled(true)
underTest.start()
// Make communal available so that communalInteractor.desiredScene accurately reflects
// scene changes instead of just returning Blank.
runBlocking { setCommunalAvailable(true) }
- setCommunalV2ConfigEnabled(true)
}
}
@@ -414,6 +426,107 @@ class CommunalSceneStartableTest(flags: FlagsParameterization) : SysuiTestCase()
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
}
+ @Test
+ @DisableFlags(FLAG_SCENE_CONTAINER)
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun glanceableHubOrientationAware_idleOnCommunal() =
+ kosmos.runTest {
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+
+ val scene by collectLastValue(communalSceneInteractor.currentScene)
+ assertThat(scene).isEqualTo(CommunalScenes.Communal)
+
+ verify(notificationShadeWindowController).setGlanceableHubOrientationAware(true)
+ }
+
+ @Test
+ @DisableFlags(FLAG_SCENE_CONTAINER)
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun glanceableHubOrientationAware_transitioningToCommunal() =
+ kosmos.runTest {
+ val progress = MutableStateFlow(0f)
+ val targetScene = CommunalScenes.Communal
+ val currentScene = CommunalScenes.Blank
+ val transitionState =
+ MutableStateFlow(
+ ObservableTransitionState.Transition(
+ fromScene = currentScene,
+ toScene = targetScene,
+ currentScene = flowOf(targetScene),
+ progress = progress,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+ communalSceneInteractor.setTransitionState(transitionState)
+
+ // Partially transition.
+ progress.value = .4f
+
+ val scene by collectLastValue(communalSceneInteractor.currentScene)
+ assertThat(scene).isEqualTo(CommunalScenes.Blank)
+
+ verify(notificationShadeWindowController).setGlanceableHubOrientationAware(true)
+ }
+
+ @Test
+ @DisableFlags(FLAG_SCENE_CONTAINER)
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun glanceableHubOrientationAware_communalToDreaming() =
+ kosmos.runTest {
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+
+ verify(notificationShadeWindowController).setGlanceableHubOrientationAware(true)
+ Mockito.clearInvocations(notificationShadeWindowController)
+
+ val progress = MutableStateFlow(0f)
+ val currentScene = CommunalScenes.Communal
+ val targetScene = CommunalScenes.Blank
+ val transitionState =
+ MutableStateFlow(
+ ObservableTransitionState.Transition(
+ fromScene = currentScene,
+ toScene = targetScene,
+ currentScene = flowOf(targetScene),
+ progress = progress,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+ communalSceneInteractor.setTransitionState(transitionState)
+
+ // Partially transitioned out of Communal scene
+ progress.value = .4f
+
+ // Started keyguard transitioning from hub -> dreaming.
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.DREAMING,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ verify(notificationShadeWindowController).setGlanceableHubOrientationAware(true)
+ Mockito.clearInvocations(notificationShadeWindowController)
+
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.DREAMING,
+ transitionState = TransitionState.RUNNING,
+ value = 0.5f,
+ )
+
+ // Transitioned to dreaming.
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.DREAMING,
+ transitionState = TransitionState.FINISHED,
+ value = 1f,
+ )
+ // Not on hub anymore, let other states take control
+ verify(notificationShadeWindowController).setGlanceableHubOrientationAware(false)
+ }
+
/**
* Advances time by duration + 1 millisecond, to ensure that tasks scheduled to run at
* currentTime + duration are scheduled.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt
index 77d7091e463a..dc21f0692c9e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt
@@ -134,7 +134,7 @@ class CommunalSceneInteractorTest(flags: FlagsParameterization) : SysuiTestCase(
underTest.snapToScene(
CommunalScenes.Communal,
"test",
- ActivityTransitionAnimator.TIMINGS.totalDuration
+ ActivityTransitionAnimator.TIMINGS.totalDuration,
)
assertThat(currentScene).isEqualTo(CommunalScenes.Blank)
advanceTimeBy(ActivityTransitionAnimator.TIMINGS.totalDuration)
@@ -269,6 +269,48 @@ class CommunalSceneInteractorTest(flags: FlagsParameterization) : SysuiTestCase(
@DisableFlags(FLAG_SCENE_CONTAINER)
@Test
+ fun isTransitioningToOrIdleOnCommunal() =
+ testScope.runTest {
+ // isIdleOnCommunal is false when not on communal.
+ val isTransitioningToOrIdleOnCommunal by
+ collectLastValue(underTest.isTransitioningToOrIdleOnCommunal)
+ assertThat(isTransitioningToOrIdleOnCommunal).isEqualTo(false)
+
+ val transitionState: MutableStateFlow<ObservableTransitionState> =
+ MutableStateFlow(
+ ObservableTransitionState.Transition(
+ fromScene = CommunalScenes.Blank,
+ toScene = CommunalScenes.Communal,
+ currentScene = flowOf(CommunalScenes.Communal),
+ progress = flowOf(0f),
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+
+ // Start transition to communal.
+ repository.setTransitionState(transitionState)
+ assertThat(isTransitioningToOrIdleOnCommunal).isEqualTo(true)
+
+ // Finish transition to communal
+ transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)
+ assertThat(isTransitioningToOrIdleOnCommunal).isEqualTo(true)
+
+ // Start transition away from communal.
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = CommunalScenes.Communal,
+ toScene = CommunalScenes.Blank,
+ currentScene = flowOf(CommunalScenes.Blank),
+ progress = flowOf(.1f),
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ assertThat(isTransitioningToOrIdleOnCommunal).isEqualTo(false)
+ }
+
+ @DisableFlags(FLAG_SCENE_CONTAINER)
+ @Test
fun isCommunalVisible() =
testScope.runTest {
// isCommunalVisible is false when not on communal.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
deleted file mode 100644
index 2f3073e8eb23..000000000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
+++ /dev/null
@@ -1,173 +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.communal.ui.viewmodel
-
-import android.content.pm.UserInfo
-import android.platform.test.annotations.EnableFlags
-import android.provider.Settings
-import android.service.dream.dreamManager
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.uiEventLoggerFake
-import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.communal.data.repository.fakeCommunalPrefsRepository
-import com.android.systemui.communal.domain.interactor.HubOnboardingInteractorTest.Companion.MAIN_USER
-import com.android.systemui.communal.shared.log.CommunalUiEvent
-import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
-import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.kosmos.runCurrent
-import com.android.systemui.kosmos.runTest
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.lifecycle.activateIn
-import com.android.systemui.plugins.activityStarter
-import com.android.systemui.settings.fakeUserTracker
-import com.android.systemui.statusbar.policy.batteryController
-import com.android.systemui.statusbar.policy.fake
-import com.android.systemui.testKosmos
-import com.android.systemui.user.data.repository.fakeUserRepository
-import com.android.systemui.util.settings.fakeSettings
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mockito.verify
-import org.mockito.kotlin.any
-
-@SmallTest
-@EnableFlags(FLAG_GLANCEABLE_HUB_V2)
-@RunWith(AndroidJUnit4::class)
-class CommunalToDreamButtonViewModelTest : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
- private val underTest: CommunalToDreamButtonViewModel by lazy {
- kosmos.communalToDreamButtonViewModel
- }
-
- @Before
- fun setUp() {
- kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
- underTest.activateIn(testScope)
- }
-
- @Test
- fun shouldShowDreamButtonOnHub_trueWhenPluggedIn() =
- with(kosmos) {
- runTest {
- batteryController.fake._isPluggedIn = true
- runCurrent()
-
- assertThat(underTest.shouldShowDreamButtonOnHub).isTrue()
- }
- }
-
- @Test
- fun shouldShowDreamButtonOnHub_falseWhenNotPluggedIn() =
- with(kosmos) {
- runTest {
- batteryController.fake._isPluggedIn = false
-
- assertThat(underTest.shouldShowDreamButtonOnHub).isFalse()
- }
- }
-
- @Test
- fun onShowDreamButtonTap_dreamsEnabled_startsDream() =
- with(kosmos) {
- runTest {
- val currentUser = fakeUserRepository.asMainUser()
- kosmos.fakeSettings.putIntForUser(
- Settings.Secure.SCREENSAVER_ENABLED,
- 1,
- currentUser.id,
- )
- runCurrent()
-
- underTest.onShowDreamButtonTap()
- runCurrent()
-
- verify(dreamManager).startDream()
- }
- }
-
- @Test
- fun onShowDreamButtonTap_dreamsDisabled_startsActivity() =
- with(kosmos) {
- runTest {
- val currentUser = fakeUserRepository.asMainUser()
- kosmos.fakeSettings.putIntForUser(
- Settings.Secure.SCREENSAVER_ENABLED,
- 0,
- currentUser.id,
- )
- runCurrent()
-
- underTest.onShowDreamButtonTap()
- runCurrent()
-
- verify(activityStarter).postStartActivityDismissingKeyguard(any(), anyInt())
- }
- }
-
- @Test
- fun shouldShowDreamButtonTooltip_trueWhenNotDismissedAndHubOnboardingDismissed() =
- kosmos.runTest {
- setSelectedUser(MAIN_USER)
- fakeCommunalPrefsRepository.setHubOnboardingDismissed(MAIN_USER)
- runCurrent()
-
- assertThat(underTest.shouldShowTooltip).isTrue()
- }
-
- @Test
- fun shouldShowDreamButtonTooltip_falseWhenNotDismissedAndHubOnboardingNotDismissed() =
- kosmos.runTest {
- runCurrent()
- assertThat(underTest.shouldShowTooltip).isFalse()
- }
-
- @Test
- fun shouldShowDreamButtonTooltip_falseWhenDismissed() =
- kosmos.runTest {
- setSelectedUser(MAIN_USER)
- fakeCommunalPrefsRepository.setDreamButtonTooltipDismissed(MAIN_USER)
- runCurrent()
-
- assertThat(underTest.shouldShowTooltip).isFalse()
- }
-
- @Test
- fun onShowDreamButtonTap_eventLogged() =
- with(kosmos) {
- runTest {
- underTest.onShowDreamButtonTap()
- runCurrent()
-
- assertThat(uiEventLoggerFake[0].eventId)
- .isEqualTo(CommunalUiEvent.COMMUNAL_HUB_SHOW_DREAM_BUTTON_TAP.id)
- }
- }
-
- private suspend fun setSelectedUser(user: UserInfo) {
- with(kosmos.fakeUserRepository) {
- setUserInfos(listOf(user))
- setSelectedUserInfo(user)
- }
- kosmos.fakeUserTracker.set(userInfos = listOf(user), selectedUserIndex = 0)
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt
index 6b9e23abd9a4..135e9a55e8b5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelTest.kt
@@ -16,28 +16,46 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.content.res.mainResources
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.domain.interactor.communalSceneInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalV2ConfigEnabled
+import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.transitions.blurConfig
+import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
+import com.android.systemui.statusbar.policy.keyguardStateController
import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.whenever
@SmallTest
@RunWith(AndroidJUnit4::class)
class GlanceableHubToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
- private val kosmos = testKosmos()
+ private val kosmos =
+ testKosmos().apply { mainResources = mContext.orCreateTestableResources.resources }
private val underTest by lazy { kosmos.glanceableHubToPrimaryBouncerTransitionViewModel }
+ @Before
+ fun setUp() {
+ with(kosmos) { setCommunalV2ConfigEnabled(true) }
+ }
+
@Test
@DisableSceneContainer
@DisableFlags(FLAG_GLANCEABLE_HUB_BLURRED_BACKGROUND)
@@ -84,4 +102,81 @@ class GlanceableHubToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
},
)
}
+
+ @Test
+ @DisableSceneContainer
+ @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun willDelayBouncerAppearAnimation_flagDisabled_isFalse() =
+ kosmos.runTest {
+ // keyguard rotation is not allowed on device.
+ whenever(keyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false)
+
+ val isIdleOnCommunal by collectLastValue(communalInteractor.isIdleOnCommunal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+ runCurrent()
+ // Device is idle on communal.
+ assertThat(isIdleOnCommunal).isTrue()
+
+ // in landscape
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = true)).isFalse()
+ // in portrait
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = false)).isFalse()
+ }
+
+ @Test
+ @DisableSceneContainer
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun willDelayBouncerAppearAnimation_keyguardRotationAllowed_isFalse() =
+ kosmos.runTest {
+ // Keyguard rotation is allowed on device.
+ whenever(keyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(true)
+
+ val isIdleOnCommunal by collectLastValue(communalInteractor.isIdleOnCommunal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+ runCurrent()
+ // Device is idle on communal.
+ assertThat(isIdleOnCommunal).isTrue()
+
+ // in landscape
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = true)).isFalse()
+ // in portrait
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = false)).isFalse()
+ }
+
+ @Test
+ @DisableSceneContainer
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun willDelayBouncerAppearAnimation_isNotIdleOnCommunal_isFalse() =
+ kosmos.runTest {
+ whenever(keyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false)
+
+ val isIdleOnCommunal by collectLastValue(communalInteractor.isIdleOnCommunal)
+ communalSceneInteractor.changeScene(CommunalScenes.Blank, "test")
+ runCurrent()
+ // Device is not on communal.
+ assertThat(isIdleOnCommunal).isFalse()
+
+ // in landscape
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = true)).isFalse()
+ // in portrait
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = false)).isFalse()
+ }
+
+ @Test
+ @DisableSceneContainer
+ @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
+ fun willDelayBouncerAppearAnimation_isIdleOnCommunalAndKeyguardRotationIsNotAllowed() =
+ kosmos.runTest {
+ whenever(keyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false)
+ val isIdleOnCommunal by collectLastValue(communalInteractor.isIdleOnCommunal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+ runCurrent()
+ // Device is idle on communal.
+ assertThat(isIdleOnCommunal).isTrue()
+
+ // Will delay in landscape
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = true)).isTrue()
+ // Won't delay in portrait
+ assertThat(underTest.willDelayAppearAnimation(isLandscape = false)).isFalse()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 764068ec1bf5..3407cd50e76f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -84,12 +84,12 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
-import java.util.List;
-import java.util.concurrent.Executor;
-
import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;
+import java.util.List;
+import java.util.concurrent.Executor;
+
@RunWith(ParameterizedAndroidJunit4.class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
@@ -410,6 +410,19 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
}
@Test
+ public void hubOrientationAware_layoutParamsUpdated() {
+ mNotificationShadeWindowController.setKeyguardShowing(false);
+ mNotificationShadeWindowController.setBouncerShowing(false);
+ mNotificationShadeWindowController.setGlanceableHubOrientationAware(true);
+ when(mKeyguardStateController.isKeyguardScreenRotationAllowed()).thenReturn(false);
+ mNotificationShadeWindowController.onConfigChanged(new Configuration());
+
+ verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+ assertThat(mLayoutParameters.getValue().screenOrientation)
+ .isEqualTo(ActivityInfo.SCREEN_ORIENTATION_USER);
+ }
+
+ @Test
public void batchApplyWindowLayoutParams_doesNotDispatchEvents() {
mNotificationShadeWindowController.setForceDozeBrightness(true);
verify(mWindowManager).updateViewLayout(any(), any());
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index f4a43a454a6f..ddad230f04e9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -151,9 +151,17 @@ class ClockRegistryTest : SysuiTestCase() {
create: (ClockId) -> ClockController = ::failFactory,
getPickerConfig: (ClockSettings) -> ClockPickerConfig = ::failPickerConfig,
): FakeClockPlugin {
- metadata.add(ClockMetadata(id))
- createCallbacks[id] = create
- pickerConfigs[id] = getPickerConfig
+ return addClock(ClockMetadata(id), create, getPickerConfig)
+ }
+
+ fun addClock(
+ metadata: ClockMetadata,
+ create: (ClockId) -> ClockController = ::failFactory,
+ getPickerConfig: (ClockSettings) -> ClockPickerConfig = ::failPickerConfig,
+ ): FakeClockPlugin {
+ this.metadata.add(metadata)
+ createCallbacks[metadata.clockId] = create
+ pickerConfigs[metadata.clockId] = getPickerConfig
return this
}
}
@@ -203,28 +211,40 @@ class ClockRegistryTest : SysuiTestCase() {
val plugin1 = FakeClockPlugin().addClock("clock_1").addClock("clock_2")
val lifecycle1 = FakeLifecycle("1", plugin1)
- val plugin2 = FakeClockPlugin().addClock("clock_3").addClock("clock_4")
+ val plugin2 =
+ FakeClockPlugin()
+ .addClock(ClockMetadata("clock_3", isDeprecated = false))
+ .addClock(ClockMetadata("clock_4", isDeprecated = true))
val lifecycle2 = FakeLifecycle("2", plugin2)
pluginListener.onPluginLoaded(plugin1, mockContext, lifecycle1)
pluginListener.onPluginLoaded(plugin2, mockContext, lifecycle2)
- val list = registry.getClocks()
assertEquals(
- list.toSet(),
setOf(
ClockMetadata(DEFAULT_CLOCK_ID),
ClockMetadata("clock_1"),
ClockMetadata("clock_2"),
ClockMetadata("clock_3"),
- ClockMetadata("clock_4"),
),
+ registry.getClocks().toSet(),
+ )
+
+ assertEquals(
+ setOf(
+ ClockMetadata(DEFAULT_CLOCK_ID),
+ ClockMetadata("clock_1"),
+ ClockMetadata("clock_2"),
+ ClockMetadata("clock_3"),
+ ClockMetadata("clock_4", isDeprecated = true),
+ ),
+ registry.getClocks(includeDeprecated = true).toSet(),
)
}
@Test
fun noPlugins_createDefaultClock() {
val clock = registry.createCurrentClock()
- assertEquals(clock, mockDefaultClock)
+ assertEquals(mockDefaultClock, clock)
}
@Test
@@ -242,18 +262,18 @@ class ClockRegistryTest : SysuiTestCase() {
pluginListener.onPluginLoaded(plugin2, mockContext, lifecycle2)
val list = registry.getClocks()
assertEquals(
- list.toSet(),
setOf(
ClockMetadata(DEFAULT_CLOCK_ID),
ClockMetadata("clock_1"),
ClockMetadata("clock_2"),
),
+ list.toSet(),
)
- assertEquals(registry.createExampleClock("clock_1"), mockClock)
- assertEquals(registry.createExampleClock("clock_2"), mockClock)
- assertEquals(registry.getClockPickerConfig("clock_1"), pickerConfig)
- assertEquals(registry.getClockPickerConfig("clock_2"), pickerConfig)
+ assertEquals(mockClock, registry.createExampleClock("clock_1"))
+ assertEquals(mockClock, registry.createExampleClock("clock_2"))
+ assertEquals(pickerConfig, registry.getClockPickerConfig("clock_1"))
+ assertEquals(pickerConfig, registry.getClockPickerConfig("clock_2"))
verify(lifecycle1, never()).unloadPlugin()
verify(lifecycle2, times(2)).unloadPlugin()
}
@@ -305,7 +325,7 @@ class ClockRegistryTest : SysuiTestCase() {
pluginListener.onPluginUnloaded(plugin2, lifecycle2)
val clock = registry.createCurrentClock()
- assertEquals(clock, mockDefaultClock)
+ assertEquals(mockDefaultClock, clock)
}
@Test
@@ -482,13 +502,13 @@ class ClockRegistryTest : SysuiTestCase() {
// Verify all plugins were correctly loaded into the registry
assertEquals(
- registry.getClocks().toSet(),
setOf(
ClockMetadata("DEFAULT"),
ClockMetadata("clock_2"),
ClockMetadata("clock_3"),
ClockMetadata("clock_4"),
),
+ registry.getClocks().toSet(),
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/ConversationNotificationProcessorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/ConversationNotificationProcessorTest.kt
index 67d0adedca6e..0caddf46cd3a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/ConversationNotificationProcessorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/ConversationNotificationProcessorTest.kt
@@ -111,13 +111,13 @@ class ConversationNotificationProcessorTest : SysuiTestCase() {
.isNotNull()
val processedSummary = nb.build().extras.getCharSequence(EXTRA_SUMMARIZED_CONTENT)
- assertThat(processedSummary.toString()).isEqualTo("x$summarization")
+ assertThat(processedSummary.toString()).isEqualTo("x $summarization")
val checkSpans = SpannableStringBuilder(processedSummary)
assertThat(
checkSpans.getSpans(
/* queryStart = */ 0,
- /* queryEnd = */ 1,
+ /* queryEnd = */ 2,
/* kind = */ ImageSpan::class.java,
)
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
index 56cd72e7725f..0bb473721446 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
@@ -15,19 +15,22 @@
*/
package com.android.systemui.statusbar.notification
+import android.animation.AnimatorTestRule
import android.util.FloatProperty
import android.util.Property
import android.view.View
-import androidx.dynamicanimation.animation.DynamicAnimation
+
import androidx.test.annotation.UiThreadTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.internal.dynamicanimation.animation.DynamicAnimation
import com.android.systemui.SysuiTestCase
import com.android.systemui.res.R
import com.android.systemui.statusbar.notification.stack.AnimationProperties
import com.android.systemui.statusbar.notification.stack.ViewState
import org.junit.Assert
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
@@ -50,6 +53,8 @@ class PhysicsPropertyAnimatorTest : SysuiTestCase() {
return _value
}
}
+ @get:Rule
+ val animatorTestRule = AnimatorTestRule(this)
private val property: PhysicsProperty =
PhysicsProperty(R.id.scale_x_animator_tag, effectiveProperty)
private var finishListener: DynamicAnimation.OnAnimationEndListener? = null
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index 285326421a14..fa185bcabf83 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator
import android.app.Flags
import android.app.NotificationChannel
+import android.app.NotificationChannel.SYSTEM_RESERVED_IDS
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.app.NotificationManager.IMPORTANCE_LOW
@@ -124,6 +125,14 @@ class ConversationCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testPrioritySectioner_doesNotClaim_classifiedConversation() {
+ val sectioner = coordinator.priorityPeopleSectioner
+ for (id in SYSTEM_RESERVED_IDS) {
+ assertFalse(sectioner.isInSection(makeClassifiedConversation(id)))
+ }
+ }
+
+ @Test
fun testPromotesImportantConversations() {
assertTrue(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)))
assertFalse(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_FULL_PERSON)))
@@ -166,6 +175,14 @@ class ConversationCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testAlertingSectioner_doesNotClaim_classifiedConversation() {
+ val sectioner = coordinator.peopleAlertingSectioner
+ for (id in SYSTEM_RESERVED_IDS) {
+ assertFalse(sectioner.isInSection(makeClassifiedConversation(id)))
+ }
+ }
+
+ @Test
fun testInAlertingPeopleSectionWhenTheImportanceIsAtLeastDefault() {
// GIVEN
val alertingEntry = makeEntryOfPeopleType(TYPE_PERSON) { setImportance(IMPORTANCE_DEFAULT) }
@@ -186,6 +203,15 @@ class ConversationCoordinatorTest : SysuiTestCase() {
@Test
@DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
+ fun testSilentSectioner_doesNotClaim_classifiedConversation() {
+ val sectioner = coordinator.peopleSilentSectioner
+ for (id in SYSTEM_RESERVED_IDS) {
+ assertFalse(sectioner.isInSection(makeClassifiedConversation(id)))
+ }
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
fun testInSilentPeopleSectionWhenTheImportanceIsLowerThanDefault() {
// GIVEN
val silentEntry = makeEntryOfPeopleType(TYPE_PERSON) { setImportance(IMPORTANCE_LOW) }
@@ -280,4 +306,17 @@ class ConversationCoordinatorTest : SysuiTestCase() {
assertEquals(type, peopleNotificationIdentifier.getPeopleNotificationType(entry))
return entry
}
+
+ private fun makeClassifiedConversation(channelId: String): NotificationEntry {
+ val channel = NotificationChannel(channelId, channelId, IMPORTANCE_LOW)
+ val entry =
+ NotificationEntryBuilder()
+ .updateRanking {
+ it.setIsConversation(true)
+ it.setShortcutInfo(mock())
+ it.setChannel(channel)
+ }
+ .build()
+ return entry
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt
index d5b2d3a68f1e..4e13dcd7576f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt
@@ -20,7 +20,6 @@ import android.app.Notification.MediaStyle
import android.media.session.MediaSession
import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
-import android.service.notification.StatusBarNotification
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.dumpManager
@@ -222,16 +221,19 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu
mock<ExpandableNotificationRow>().apply {
whenever(isMediaRow).thenReturn(true)
}
- sbn = SbnBuilder().setNotification(
- Notification.Builder(context, "channel").setStyle(
- MediaStyle().setMediaSession(
- MediaSession(
- context,
- "tag"
- ).sessionToken
+ sbn =
+ SbnBuilder()
+ .setNotification(
+ Notification.Builder(context, "channel")
+ .setStyle(
+ MediaStyle()
+ .setMediaSession(
+ MediaSession(context, "tag").sessionToken
+ )
+ )
+ .build()
)
- ).build()
- ).build()
+ .build()
}
collectionListener.onEntryAdded(fakeEntry)
@@ -631,6 +633,132 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu
}
}
+ @Test
+ fun seenNotificationOnKeyguardMarkedAsSeenIfUpdatedBySystemServer() {
+ // GIVEN: Keyguard is showing, not dozing, unseen notification is present
+ keyguardRepository.setKeyguardShowing(true)
+ keyguardRepository.setIsDozing(false)
+ runKeyguardCoordinatorTest {
+ val fakeEntry = NotificationEntryBuilder().build()
+ collectionListener.onEntryAdded(fakeEntry)
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
+ )
+ testScheduler.runCurrent()
+
+ // WHEN: five seconds have passed
+ testScheduler.advanceTimeBy(5.seconds)
+ testScheduler.runCurrent()
+
+ // WHEN: Keyguard is no longer showing
+ keyguardRepository.setKeyguardShowing(false)
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Gone),
+ stateTransition = TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE),
+ )
+
+ // WHEN: the notification is updated by the Server
+ collectionListener.onEntryUpdated(fakeEntry, UpdateSource.SystemServer)
+ testScheduler.runCurrent()
+
+ // WHEN: Keyguard is shown again
+ keyguardRepository.setKeyguardShowing(true)
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Lockscreen),
+ stateTransition = TransitionStep(KeyguardState.GONE, KeyguardState.AOD),
+ )
+
+ // THEN: The notification is still recognized as "seen" and is filtered out.
+ assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
+ }
+ }
+
+ @Test
+ fun seenNotificationOnKeyguardMarkedAsSeenIfUpdatedBySystemUi() {
+ // GIVEN: Keyguard is showing, not dozing, unseen notification is present
+ keyguardRepository.setKeyguardShowing(true)
+ keyguardRepository.setIsDozing(false)
+ runKeyguardCoordinatorTest {
+ val fakeEntry = NotificationEntryBuilder().build()
+ collectionListener.onEntryAdded(fakeEntry)
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
+ )
+ testScheduler.runCurrent()
+
+ // WHEN: five seconds have passed
+ testScheduler.advanceTimeBy(5.seconds)
+ testScheduler.runCurrent()
+
+ // WHEN: Keyguard is no longer showing
+ keyguardRepository.setKeyguardShowing(false)
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Gone),
+ stateTransition = TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE),
+ )
+
+ // WHEN: the notification is updated by the SystemUi
+ collectionListener.onEntryUpdated(fakeEntry, UpdateSource.SystemUi)
+ testScheduler.runCurrent()
+
+ // WHEN: Keyguard is shown again
+ keyguardRepository.setKeyguardShowing(true)
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Lockscreen),
+ stateTransition = TransitionStep(KeyguardState.GONE, KeyguardState.AOD),
+ )
+
+ // THEN: The notification is still recognized as "seen" and is filtered out.
+ assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
+ }
+ }
+
+ @Test
+ fun seenNotificationOnKeyguardMarkedAsUnseenIfUpdatedByApp() {
+ // GIVEN: Keyguard is showing, not dozing, unseen notification is present
+ keyguardRepository.setKeyguardShowing(true)
+ keyguardRepository.setIsDozing(false)
+ runKeyguardCoordinatorTest {
+ val fakeEntry = NotificationEntryBuilder().build()
+ collectionListener.onEntryAdded(fakeEntry)
+ keyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ this.testScheduler,
+ )
+ testScheduler.runCurrent()
+
+ // WHEN: five seconds have passed
+ testScheduler.advanceTimeBy(5.seconds)
+ testScheduler.runCurrent()
+
+ // WHEN: Keyguard is no longer showing
+ keyguardRepository.setKeyguardShowing(false)
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Gone),
+ stateTransition = TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE),
+ )
+
+ // WHEN: the notification is updated by the App
+ collectionListener.onEntryUpdated(fakeEntry, UpdateSource.App)
+ testScheduler.runCurrent()
+
+ // WHEN: Keyguard is shown again
+ keyguardRepository.setKeyguardShowing(true)
+ kosmos.setTransition(
+ sceneTransition = Idle(Scenes.Lockscreen),
+ stateTransition = TransitionStep(KeyguardState.GONE, KeyguardState.AOD),
+ )
+
+ // THEN: The notification is now recognized as "unseen" and is not filtered out.
+ assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse()
+ }
+ }
+
private fun runKeyguardCoordinatorTest(
testBlock: suspend KeyguardCoordinatorTestScope.() -> Unit
) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
index 961616c99cb1..3d1fdee306f4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
@@ -22,6 +22,8 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.accessibility.data.repository.FakeAccessibilityRepository
import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.testKosmos
+import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -32,12 +34,16 @@ import org.junit.runner.RunWith
@SmallTest
class ActivatableNotificationViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
// fakes
private val a11yRepo = FakeAccessibilityRepository()
// real impls
private val a11yInteractor = AccessibilityInteractor(a11yRepo)
- private val underTest = ActivatableNotificationViewModel(a11yInteractor)
+ private val windowRootViewBlurInteractor = kosmos.windowRootViewBlurInteractor
+ private val underTest = ActivatableNotificationViewModel(a11yInteractor,
+ windowRootViewBlurInteractor)
@Test
fun isTouchable_whenA11yTouchExplorationDisabled() = runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
index 4a761917b693..cb4642cc21be 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
@@ -18,9 +18,11 @@ package com.android.systemui.statusbar.notification.stack
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.AnimatorTestRule
import com.android.systemui.res.R
@@ -44,6 +46,7 @@ import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.description
import org.mockito.Mockito.eq
import org.mockito.Mockito.verify
+import org.mockito.kotlin.doNothing
private const val VIEW_HEIGHT = 100
private const val FULL_SHADE_APPEAR_TRANSLATION = 300
@@ -53,18 +56,20 @@ private const val HEADS_UP_ABOVE_SCREEN = 80
@RunWith(AndroidJUnit4::class)
@RunWithLooper
class StackStateAnimatorTest : SysuiTestCase() {
+
+ @get:Rule val setFlagsRule = SetFlagsRule()
@get:Rule val animatorTestRule = AnimatorTestRule(this)
private lateinit var stackStateAnimator: StackStateAnimator
private lateinit var headsUpAnimator: HeadsUpAnimator
private val stackScroller: NotificationStackScrollLayout = mock()
private val view: ExpandableView = mock()
- private val viewState: ExpandableViewState =
- ExpandableViewState().apply { height = VIEW_HEIGHT }
+ private lateinit var viewState: ExpandableViewState
private val runnableCaptor: ArgumentCaptor<Runnable> = argumentCaptor()
@Before
fun setUp() {
+ viewState = ExpandableViewState().apply { height = VIEW_HEIGHT }
overrideResource(
R.dimen.go_to_full_shade_appearing_translation,
FULL_SHADE_APPEAR_TRANSLATION,
@@ -153,6 +158,7 @@ class StackStateAnimatorTest : SysuiTestCase() {
)
}
+ @DisableFlags(Flags.FLAG_PHYSICAL_NOTIFICATION_MOVEMENT)
@Test
@EnableFlags(NotificationsHunSharedAnimationValues.FLAG_NAME)
fun startAnimationForEvents_headsUpFromBottom_startsHeadsUpAppearAnim_flagOn() {
@@ -238,6 +244,32 @@ class StackStateAnimatorTest : SysuiTestCase() {
.removeFromTransientContainer()
}
+ @EnableFlags(Flags.FLAG_PHYSICAL_NOTIFICATION_MOVEMENT)
+ @Test
+ fun startAnimationForEvents_startsHeadsUpDisappearAnim_physical() {
+ val disappearDuration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR.toLong()
+ val event = AnimationEvent(view, AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR)
+ clearInvocations(view)
+ stackStateAnimator.startAnimationForEvents(arrayListOf(event), 0)
+
+ verify(view)
+ .performRemoveAnimation(
+ /* duration= */ eq(disappearDuration),
+ /* delay= */ eq(0L),
+ /* translationDirection= */ eq(0f),
+ /* isHeadsUpAnimation= */ eq(true),
+ /* isHeadsUpCycling= */ eq(false),
+ /* onStartedRunnable= */ any(),
+ /* onFinishedRunnable= */ runnableCaptor.capture(),
+ /* animationListener= */ any(),
+ /* clipSide= */ eq(ExpandableView.ClipSide.BOTTOM),
+ )
+
+ runnableCaptor.value.run() // execute the end runnable
+ verify(view, description("should be called at the end of the disappear animation"))
+ .removeFromTransientContainer()
+ }
+
@Test
fun initView_updatesResources() {
// Given: the resource values are initialized in the SSA
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
index ef415c918f91..6ee1c4ddf8e3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.stack
+import android.animation.AnimatorTestRule
import android.animation.ValueAnimator
import android.view.View
import androidx.test.annotation.UiThreadTest
@@ -28,6 +29,7 @@ import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator
import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.TAG_ANIMATOR_TRANSLATION_Y
import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.Y_TRANSLATION
import org.junit.Assert
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.math.log2
@@ -38,6 +40,8 @@ import kotlin.math.sqrt
@UiThreadTest
class ViewStateTest : SysuiTestCase() {
private val viewState = ViewState(true /* usePhysicsForMovement */)
+ @get:Rule
+ val animatorTestRule = AnimatorTestRule(this)
@Suppress("DIVISION_BY_ZERO")
@Test
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
index 7426f061b84c..0ef62a32a9c4 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
@@ -53,5 +53,21 @@ interface ClockProvider {
/** Identifies a clock design */
typealias ClockId = String
-/** Some data about a clock design */
-data class ClockMetadata(val clockId: ClockId)
+/** Some metadata about a clock design */
+data class ClockMetadata(
+ /** Id for the clock design. */
+ val clockId: ClockId,
+
+ /**
+ * true if this clock is deprecated and should not be used. The ID may still show up in certain
+ * locations to help migrations, but it will not be selectable by new users.
+ */
+ val isDeprecated: Boolean = false,
+
+ /**
+ * Optional mapping of a legacy clock to a new id. This will map users that already are using
+ * `clockId` to the `replacementTarget` instead. The provider should still support the old id
+ * w/o crashing, but can consider it deprecated and the id reserved.
+ */
+ val replacementTarget: ClockId? = null,
+)
diff --git a/packages/SystemUI/res/layout/volume_dialog_top_section.xml b/packages/SystemUI/res/layout/volume_dialog_top_section.xml
index 4fc20e218c5e..29f52480bfe0 100644
--- a/packages/SystemUI/res/layout/volume_dialog_top_section.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_top_section.xml
@@ -22,7 +22,6 @@
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
- android:layoutDirection="ltr"
android:paddingEnd="@dimen/volume_dialog_ringer_drawer_diff_end_margin"
app:layoutDescription="@xml/volume_dialog_ringer_drawer_motion_scene">
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6ff1240c5e60..43ea2c3f7633 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1024,6 +1024,12 @@
<string name="hearing_devices_ambient_control_left">Left</string>
<!-- QuickSettings: The text to show the control is for right side device. [CHAR LIMIT=30] -->
<string name="hearing_devices_ambient_control_right">Right</string>
+ <!-- QuickSettings: Content description for unified ambient control slider. [CHAR LIMIT=NONE] -->
+ <string name="hearing_devices_ambient_control_description">Surroundings</string>
+ <!-- QuickSettings: Content description for left ambient control slider. [CHAR LIMIT=NONE] -->
+ <string name="hearing_devices_ambient_control_left_description">Left surroundings</string>
+ <!-- QuickSettings: Content description for left ambient control slider. [CHAR LIMIT=NONE] -->
+ <string name="hearing_devices_ambient_control_right_description">Right surroundings</string>
<!-- QuickSettings: Content description for a button, that expands ambient volume sliders [CHAR_LIMIT=NONE] -->
<string name="hearing_devices_ambient_expand_controls">Expand to left and right separated controls</string>
<!-- QuickSettings: Content description for a button, that collapses ambient volume sliders [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 5b96e5085fd2..4431ddadc8de 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -871,6 +871,7 @@
</style>
<style name="MediaPlayer.SessionAction.Primary" parent="MediaPlayer.SessionAction">
+ <item name="android:tint">@android:color/system_on_primary_dark</item>
<item name="android:background">@drawable/qs_media_round_button_background</item>
<item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
</style>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 73dc28230e65..e2f3955263a1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -172,6 +172,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private boolean mIsDragging;
private float mStartTouchY = -1;
private boolean mDisappearAnimRunning;
+ private boolean mIsAppearAnimationDelayed;
private SwipeListener mSwipeListener;
private ViewMode mViewMode = new DefaultViewMode();
private boolean mIsInteractable;
@@ -583,6 +584,10 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
return false;
}
+ boolean isAppearAnimationDelayed() {
+ return mIsAppearAnimationDelayed;
+ }
+
void addMotionEventListener(Gefingerpoken listener) {
mMotionEventListeners.add(listener);
}
@@ -624,6 +629,19 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
mViewMode.startAppearAnimation(securityMode);
}
+ /**
+ * Set view translationY and alpha as we delay bouncer animation.
+ */
+ public void setupForDelayedAppear() {
+ setTranslationY(0f);
+ setAlpha(0f);
+ setIsAppearAnimationDelayed(true);
+ }
+
+ public void setIsAppearAnimationDelayed(boolean isDelayed) {
+ mIsAppearAnimationDelayed = isDelayed;
+ }
+
private void beginJankInstrument(int cuj) {
KeyguardInputView securityView = mSecurityViewFlipper.getSecurityView();
if (securityView == null) return;
@@ -812,6 +830,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
public void reset() {
mViewMode.reset();
mDisappearAnimRunning = false;
+ mIsAppearAnimationDelayed = false;
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index d10fce416150..198c1cb08647 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -18,6 +18,7 @@ package com.android.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISSIBLE_KEYGUARD;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
@@ -385,6 +386,10 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
boolean useSplitBouncer = orientation == ORIENTATION_LANDSCAPE;
mSecurityViewFlipperController.updateConstraints(useSplitBouncer);
}
+ if (orientation == ORIENTATION_PORTRAIT) {
+ // If there is any delayed bouncer appear animation it can start now
+ startAppearAnimationIfDelayed();
+ }
}
@Override
@@ -845,6 +850,16 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
}
}
+ /** Start appear animation which was previously delayed from opening bouncer in landscape. */
+ public void startAppearAnimationIfDelayed() {
+ if (!mView.isAppearAnimationDelayed()) {
+ return;
+ }
+ setAlpha(1f);
+ appear();
+ mView.setIsAppearAnimationDelayed(false);
+ }
+
/** Called when the bouncer changes visibility. */
public void onBouncerVisibilityChanged(boolean isVisible) {
if (!isVisible) {
@@ -1301,4 +1316,13 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
mView.setTranslationY(scaledFraction * mTranslationY);
}
+
+ /** Set up view for delayed appear animation. */
+ public void setupForDelayedAppear() {
+ mView.setupForDelayedAppear();
+ }
+
+ public boolean isLandscapeOrientation() {
+ return mLastOrientation == Configuration.ORIENTATION_LANDSCAPE;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
index 5247acc94e03..33c9eb17cd44 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
@@ -327,8 +327,19 @@ public class AmbientVolumeLayout extends LinearLayout implements AmbientVolumeUi
slider.addOnChangeListener(mSliderOnChangeListener);
if (side == SIDE_LEFT) {
slider.setTitle(mContext.getString(R.string.hearing_devices_ambient_control_left));
+ slider.setContentDescription(
+ mContext.getString(R.string.hearing_devices_ambient_control_left));
+ slider.setSliderContentDescription(
+ mContext.getString(R.string.hearing_devices_ambient_control_left_description));
} else if (side == SIDE_RIGHT) {
slider.setTitle(mContext.getString(R.string.hearing_devices_ambient_control_right));
+ slider.setContentDescription(
+ mContext.getString(R.string.hearing_devices_ambient_control_right));
+ slider.setSliderContentDescription(
+ mContext.getString(R.string.hearing_devices_ambient_control_right_description));
+ } else {
+ slider.setSliderContentDescription(
+ mContext.getString(R.string.hearing_devices_ambient_control_description));
}
mSideToSliderMap.put(side, slider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
index 1a068c4229c9..5c0ad3dcf421 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
@@ -92,6 +92,11 @@ public class AmbientVolumeSlider extends LinearLayout {
mSlider = requireViewById(R.id.ambient_volume_slider);
mSlider.addOnSliderTouchListener(mSliderTouchListener);
mSlider.addOnChangeListener(mSliderChangeListener);
+
+ setFocusable(false);
+ setClickable(false);
+ mSlider.setFocusable(false);
+ mSlider.setClickable(false);
}
/**
@@ -178,6 +183,13 @@ public class AmbientVolumeSlider extends LinearLayout {
return (int) Math.ceil((value - min) / levelGap);
}
+ /** Sets the content description to the ambient volume slider. */
+ public void setSliderContentDescription(CharSequence contentDescription) {
+ if (mSlider != null) {
+ mSlider.setContentDescription(contentDescription);
+ }
+ }
+
/** Interface definition for a callback invoked when a slider's value is changed. */
public interface OnChangeListener {
/** Called when the finger is take off from the slider. */
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt
index d8e7a168ef3c..97de78c41af7 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.kt
@@ -18,6 +18,7 @@ package com.android.systemui.ambient.touch
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
+import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.Region
import android.util.Log
@@ -36,6 +37,7 @@ import com.android.systemui.ambient.touch.dagger.BouncerSwipeModule
import com.android.systemui.ambient.touch.scrim.ScrimController
import com.android.systemui.ambient.touch.scrim.ScrimManager
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.plugins.ActivityStarter
@@ -46,6 +48,7 @@ import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.wm.shell.animation.FlingAnimationUtils
import java.util.Optional
import javax.inject.Inject
@@ -82,6 +85,8 @@ constructor(
private val sceneInteractor: SceneInteractor,
private val shadeRepository: ShadeRepository,
private val windowRootViewProvider: Optional<Provider<WindowRootView>>,
+ private val keyguardStateController: KeyguardStateController,
+ communalSettingsInteractor: CommunalSettingsInteractor,
) : TouchHandler {
/** An interface for creating ValueAnimators. */
interface ValueAnimatorCreator {
@@ -101,6 +106,8 @@ constructor(
private var capture: Boolean? = null
private var expanded: Boolean = false
private var touchSession: TouchSession? = null
+ private var isUserTrackingExpansionDisabled: Boolean = false
+ private var isKeyguardScreenRotationAllowed: Boolean = false
private val scrimManagerCallback =
ScrimManager.Callback { controller ->
currentScrimController?.reset()
@@ -121,6 +128,9 @@ constructor(
distanceX: Float,
distanceY: Float,
): Boolean {
+ val isLandscape =
+ windowRootView.resources.configuration.orientation ==
+ Configuration.ORIENTATION_LANDSCAPE
if (capture == null) {
capture =
if (Flags.dreamOverlayBouncerSwipeDirectionFiltering()) {
@@ -137,7 +147,9 @@ constructor(
// reset expanding
expanded = false
// Since the user is dragging the bouncer up, set scrimmed to false.
- currentScrimController?.show()
+ if (isKeyguardScreenRotationAllowed || !isLandscape) {
+ currentScrimController?.show(false)
+ }
if (SceneContainerFlag.isEnabled) {
sceneInteractor.onRemoteUserInputStarted("bouncer touch handler")
@@ -172,6 +184,37 @@ constructor(
return true
}
+ if (touchSession == null) {
+ return true
+ }
+ val screenTravelPercentage =
+ (abs((y - e2.y).toDouble()) / touchSession!!.bounds.height()).toFloat()
+
+ if (communalSettingsInteractor.isV2FlagEnabled()) {
+ if (isUserTrackingExpansionDisabled) return true
+ // scrolling up in landscape orientation but device doesn't allow keyguard
+ // screen rotation
+ if (y > e2.y && !isKeyguardScreenRotationAllowed && isLandscape) {
+ velocityTracker!!.computeCurrentVelocity(1000)
+ currentExpansion = 1 - screenTravelPercentage
+ expanded =
+ shouldExpandBouncer(
+ velocityTracker!!.yVelocity,
+ velocityTracker!!.xVelocity,
+ EXPANSION_FROM_LANDSCAPE_THRESHOLD,
+ currentExpansion,
+ )
+ if (expanded) {
+ // Once scroll past the percentage threshold, show bouncer scrimmed,
+ // so that user won't be required to drag up and then right to keep
+ // bouncer open after screen rotates to portrait.
+ currentScrimController?.show(true)
+ isUserTrackingExpansionDisabled = true
+ }
+ return true
+ }
+ }
+
if (SceneContainerFlag.isEnabled) {
windowRootView.dispatchTouchEvent(e2)
} else {
@@ -182,12 +225,7 @@ constructor(
// is fully hidden at full expansion (1) and fully visible when fully
// collapsed
// (0).
- touchSession?.apply {
- val screenTravelPercentage =
- (abs((this@outer.y - e2.y).toDouble()) / getBounds().height())
- .toFloat()
- setPanelExpansion(1 - screenTravelPercentage)
- }
+ touchSession?.apply { setPanelExpansion(1 - screenTravelPercentage) }
}
}
@@ -262,6 +300,7 @@ constructor(
}
scrimManager.addCallback(scrimManagerCallback)
currentScrimController = scrimManager.currentController
+ isKeyguardScreenRotationAllowed = keyguardStateController.isKeyguardScreenRotationAllowed()
shadeRepository.setLegacyShadeTracking(true)
session.registerCallback {
@@ -271,6 +310,7 @@ constructor(
scrimManager.removeCallback(scrimManagerCallback)
capture = null
touchSession = null
+ isUserTrackingExpansionDisabled = false
if (!Flags.communalBouncerDoNotModifyPluginOpen()) {
notificationShadeWindowController.setForcePluginOpen(false, this)
}
@@ -299,14 +339,25 @@ constructor(
return
}
+ // We are already in progress of opening bouncer scrimmed
+ if (isUserTrackingExpansionDisabled) {
+ // User is done scrolling, reset
+ isUserTrackingExpansionDisabled = false
+ return
+ }
+
// We must capture the resulting velocities as resetMonitor() will clear these
// values.
velocityTracker!!.computeCurrentVelocity(1000)
val verticalVelocity = velocityTracker!!.yVelocity
- val horizontalVelocity = velocityTracker!!.xVelocity
- val velocityVector =
- hypot(horizontalVelocity.toDouble(), verticalVelocity.toDouble()).toFloat()
- expanded = !flingRevealsOverlay(verticalVelocity, velocityVector)
+ expanded =
+ shouldExpandBouncer(
+ verticalVelocity,
+ velocityTracker!!.xVelocity,
+ FLING_PERCENTAGE_THRESHOLD,
+ currentExpansion,
+ )
+
val expansion =
if (expanded!!) KeyguardBouncerConstants.EXPANSION_VISIBLE
else KeyguardBouncerConstants.EXPANSION_HIDDEN
@@ -339,11 +390,27 @@ constructor(
return animator
}
- protected fun flingRevealsOverlay(velocity: Float, velocityVector: Float): Boolean {
+ private fun shouldExpandBouncer(
+ verticalVelocity: Float,
+ horizontalVelocity: Float,
+ threshold: Float,
+ expansion: Float,
+ ): Boolean {
+ val velocityVector =
+ hypot(horizontalVelocity.toDouble(), verticalVelocity.toDouble()).toFloat()
+ return !flingRevealsOverlay(verticalVelocity, velocityVector, threshold, expansion)
+ }
+
+ protected fun flingRevealsOverlay(
+ velocity: Float,
+ velocityVector: Float,
+ threshold: Float,
+ expansion: Float,
+ ): Boolean {
// Fully expand the space above the bouncer, if the user has expanded the bouncer less
// than halfway or final velocity was positive, indicating a downward direction.
return if (abs(velocityVector.toDouble()) < flingAnimationUtils.minVelocityPxPerSecond) {
- currentExpansion > FLING_PERCENTAGE_THRESHOLD
+ expansion > threshold
} else {
velocity > 0
}
@@ -390,6 +457,7 @@ constructor(
companion object {
const val FLING_PERCENTAGE_THRESHOLD = 0.5f
+ const val EXPANSION_FROM_LANDSCAPE_THRESHOLD = 0.95f
private const val TAG = "BouncerSwipeTouchHandler"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java
index 94c998267598..6f2dd799c409 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/BouncerScrimController.java
@@ -33,8 +33,8 @@ public class BouncerScrimController implements ScrimController {
}
@Override
- public void show() {
- mStatusBarKeyguardViewManager.showPrimaryBouncer(false);
+ public void show(boolean scrimmed) {
+ mStatusBarKeyguardViewManager.showPrimaryBouncer(scrimmed);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java
index 00543523ec2e..90cbd258f03e 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/scrim/ScrimController.java
@@ -25,8 +25,9 @@ import com.android.systemui.shade.ShadeExpansionChangeEvent;
public interface ScrimController {
/**
* Called at the start of expansion before any expansion amount updates.
+ * @param scrimmed true when the bouncer should show scrimmed, false when user will be dragging.
*/
- default void show() {
+ default void show(boolean scrimmed) {
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
index 7f268315e566..5d64219c7f90 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
@@ -15,6 +15,7 @@ import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
import com.android.systemui.log.BouncerLogger
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
@@ -30,6 +31,8 @@ data class LegacyBouncerDependencies
constructor(
val viewModel: KeyguardBouncerViewModel,
val primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
+ val glanceableHubToPrimaryBouncerTransitionViewModel:
+ GlanceableHubToPrimaryBouncerTransitionViewModel,
val componentFactory: KeyguardBouncerComponent.Factory,
val messageAreaControllerFactory: KeyguardMessageAreaController.Factory,
val bouncerMessageInteractor: BouncerMessageInteractor,
@@ -82,6 +85,7 @@ constructor(
view,
deps.viewModel,
deps.primaryBouncerToGoneTransitionViewModel,
+ deps.glanceableHubToPrimaryBouncerTransitionViewModel,
deps.componentFactory,
deps.messageAreaControllerFactory,
deps.bouncerMessageInteractor,
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
index 7d8945a5b4a7..45f0e13c185e 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
@@ -33,6 +33,7 @@ import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.bouncer.ui.BouncerViewDelegate
import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.log.BouncerLogger
@@ -49,6 +50,8 @@ object KeyguardBouncerViewBinder {
view: ViewGroup,
viewModel: KeyguardBouncerViewModel,
primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
+ glanceableHubToPrimaryBouncerTransitionViewModel:
+ GlanceableHubToPrimaryBouncerTransitionViewModel,
componentFactory: KeyguardBouncerComponent.Factory,
messageAreaControllerFactory: KeyguardMessageAreaController.Factory,
bouncerMessageInteractor: BouncerMessageInteractor,
@@ -133,7 +136,20 @@ object KeyguardBouncerViewBinder {
/* turningOff= */ false
)
securityContainerController.setInitialMessage()
- securityContainerController.appear()
+ // Delay bouncer appearing animation when opening it from the
+ // glanceable hub in landscape, until after orientation changes
+ // to portrait. This prevents bouncer from showing in landscape
+ // layout, if bouncer rotation is not allowed.
+ if (
+ glanceableHubToPrimaryBouncerTransitionViewModel
+ .willDelayAppearAnimation(
+ securityContainerController.isLandscapeOrientation
+ )
+ ) {
+ securityContainerController.setupForDelayedAppear()
+ } else {
+ securityContainerController.appear()
+ }
securityContainerController.onResume(
KeyguardSecurityView.SCREEN_ON
)
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
index e36e85565293..49b0bb63545f 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
@@ -29,10 +29,17 @@ import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalScenes.isCommunal
import com.android.systemui.communal.shared.model.CommunalTransitionKeys
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.Edge
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.emitOnStart
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
@@ -45,6 +52,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.withContext
@@ -60,10 +68,12 @@ constructor(
private val communalInteractor: CommunalInteractor,
private val communalSettingsInteractor: CommunalSettingsInteractor,
private val communalSceneInteractor: CommunalSceneInteractor,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val keyguardInteractor: KeyguardInteractor,
private val systemSettings: SystemSettings,
private val notificationShadeWindowController: NotificationShadeWindowController,
@Background private val bgScope: CoroutineScope,
+ @Application private val applicationScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
private val uiEventLogger: UiEventLogger,
) : CoreStartable {
@@ -154,6 +164,25 @@ constructor(
}
}
}
+
+ if (communalSettingsInteractor.isV2FlagEnabled()) {
+ applicationScope.launch(context = mainDispatcher) {
+ anyOf(
+ communalSceneInteractor.isTransitioningToOrIdleOnCommunal,
+ // when transitioning from hub to dream, allow hub to stay at the current
+ // orientation, as keyguard doesn't allow rotation by default.
+ keyguardTransitionInteractor.isInTransition(
+ edge = Edge.create(from = Scenes.Communal, to = DREAMING),
+ edgeWithoutSceneContainer =
+ Edge.create(from = GLANCEABLE_HUB, to = DREAMING),
+ ),
+ )
+ .distinctUntilChanged()
+ .collectLatest {
+ notificationShadeWindowController.setGlanceableHubOrientationAware(it)
+ }
+ }
+ }
}
private fun cancelHubTimeout() {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
index 3d9e93036dbc..fed99d71fa3b 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
@@ -307,6 +307,21 @@ constructor(
initialValue = false,
)
+ /** Flow that emits a boolean if transitioning to or idle on communal scene. */
+ val isTransitioningToOrIdleOnCommunal: Flow<Boolean> =
+ transitionState
+ .map {
+ (it is ObservableTransitionState.Idle &&
+ it.currentScene == CommunalScenes.Communal) ||
+ (it is ObservableTransitionState.Transition &&
+ it.toContent == CommunalScenes.Communal)
+ }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = false,
+ )
+
private companion object {
const val TAG = "CommunalSceneInteractor"
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
deleted file mode 100644
index b531d159acde..000000000000
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
+++ /dev/null
@@ -1,124 +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.communal.ui.viewmodel
-
-import android.annotation.SuppressLint
-import android.app.DreamManager
-import android.content.Intent
-import android.provider.Settings
-import androidx.compose.runtime.getValue
-import com.android.internal.logging.UiEventLogger
-import com.android.systemui.communal.domain.interactor.CommunalPrefsInteractor
-import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
-import com.android.systemui.communal.shared.log.CommunalUiEvent
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.lifecycle.ExclusiveActivatable
-import com.android.systemui.lifecycle.Hydrator
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.policy.BatteryController
-import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
-import com.android.systemui.util.kotlin.BooleanFlowOperators.not
-import com.android.systemui.util.kotlin.isDevicePluggedIn
-import com.android.systemui.util.kotlin.sample
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.awaitCancellation
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.receiveAsFlow
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-
-class CommunalToDreamButtonViewModel
-@AssistedInject
-constructor(
- @Background private val backgroundContext: CoroutineContext,
- batteryController: BatteryController,
- private val prefsInteractor: CommunalPrefsInteractor,
- private val settingsInteractor: CommunalSettingsInteractor,
- private val activityStarter: ActivityStarter,
- private val dreamManager: DreamManager,
- private val uiEventLogger: UiEventLogger,
-) : ExclusiveActivatable() {
-
- private val hydrator = Hydrator("CommunalToDreamButtonViewModel.hydrator")
- private val _requests = Channel<Unit>(Channel.BUFFERED)
-
- /** Whether we should show a button on hub to switch to dream. */
- val shouldShowDreamButtonOnHub: Boolean by
- hydrator.hydratedStateOf(
- traceName = "shouldShowDreamButtonOnHub",
- initialValue = false,
- source = batteryController.isDevicePluggedIn().distinctUntilChanged(),
- )
-
- /** Return whether to show the dream button tooltip. */
- val shouldShowTooltip: Boolean by
- hydrator.hydratedStateOf(
- traceName = "shouldShowTooltip",
- initialValue = false,
- source =
- allOf(
- not(prefsInteractor.isDreamButtonTooltipDismissed),
- prefsInteractor.isHubOnboardingDismissed,
- ),
- )
-
- /** Set the dream button tooltip to be dismissed. */
- fun setDreamButtonTooltipDismissed() {
- prefsInteractor.setDreamButtonTooltipDismissed()
- }
-
- /** Handle a tap on the "show dream" button. */
- fun onShowDreamButtonTap() {
- uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_SHOW_DREAM_BUTTON_TAP)
- _requests.trySend(Unit)
- }
-
- @SuppressLint("MissingPermission")
- override suspend fun onActivated(): Nothing = coroutineScope {
- launch {
- _requests
- .receiveAsFlow()
- .sample(settingsInteractor.isScreensaverEnabled)
- .collectLatest { enabled ->
- withContext(backgroundContext) {
- if (enabled) {
- dreamManager.startDream()
- } else {
- activityStarter.postStartActivityDismissingKeyguard(
- Intent(Settings.ACTION_DREAM_SETTINGS),
- 0,
- )
- }
- }
- }
- }
-
- launch { hydrator.activate() }
-
- awaitCancellation()
- }
-
- @AssistedFactory
- interface Factory {
- fun create(): CommunalToDreamButtonViewModel
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/grid/ui/compose/SpannedGrids.kt b/packages/SystemUI/src/com/android/systemui/grid/ui/compose/SpannedGrids.kt
index 96ef03c996a9..e06c228e24b2 100644
--- a/packages/SystemUI/src/com/android/systemui/grid/ui/compose/SpannedGrids.kt
+++ b/packages/SystemUI/src/com/android/systemui/grid/ui/compose/SpannedGrids.kt
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.systemui.grid.ui.compose
+import androidx.collection.IntIntPair
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
@@ -24,7 +24,6 @@ import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.semantics.CollectionInfo
import androidx.compose.ui.semantics.CollectionItemInfo
import androidx.compose.ui.semantics.collectionInfo
@@ -34,6 +33,8 @@ import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastForEachIndexed
+import androidx.compose.ui.util.fastMapIndexed
import kotlin.math.max
/**
@@ -65,7 +66,11 @@ fun HorizontalSpannedGrid(
spans: List<Int>,
modifier: Modifier = Modifier,
keys: (spanIndex: Int) -> Any = { it },
- composables: @Composable BoxScope.(spanIndex: Int) -> Unit,
+ composables:
+ @Composable
+ BoxScope.(
+ spanIndex: Int, row: Int, isFirstInColumn: Boolean, isLastInColumn: Boolean,
+ ) -> Unit,
) {
SpannedGrid(
primarySpaces = rows,
@@ -80,7 +85,7 @@ fun HorizontalSpannedGrid(
}
/**
- * Horizontal (non lazy) grid that supports [spans] for its elements.
+ * Vertical (non lazy) grid that supports [spans] for its elements.
*
* The elements will be laid down horizontally first, and then by rows. So assuming LTR layout, it
* will be (for a span list `[2, 1, 2, 1, 1, 1, 1, 1]` and 4 columns):
@@ -107,7 +112,9 @@ fun VerticalSpannedGrid(
spans: List<Int>,
modifier: Modifier = Modifier,
keys: (spanIndex: Int) -> Any = { it },
- composables: @Composable BoxScope.(spanIndex: Int) -> Unit,
+ composables:
+ @Composable
+ BoxScope.(spanIndex: Int, column: Int, isFirstInRow: Boolean, isLastInRow: Boolean) -> Unit,
) {
SpannedGrid(
primarySpaces = columns,
@@ -130,7 +137,9 @@ private fun SpannedGrid(
isVertical: Boolean,
modifier: Modifier = Modifier,
keys: (spanIndex: Int) -> Any = { it },
- composables: @Composable BoxScope.(spanIndex: Int) -> Unit,
+ composables:
+ @Composable
+ BoxScope.(spanIndex: Int, secondaryAxis: Int, isFirst: Boolean, isLast: Boolean) -> Unit,
) {
val crossAxisArrangement = Arrangement.spacedBy(crossAxisSpacing)
spans.forEachIndexed { index, span ->
@@ -139,7 +148,6 @@ private fun SpannedGrid(
"expected rance of [1, $primarySpaces]"
}
}
-
if (isVertical) {
check(crossAxisSpacing >= 0.dp) { "Negative columnSpacing $crossAxisSpacing" }
check(mainAxisSpacing >= 0.dp) { "Negative rowSpacing $mainAxisSpacing" }
@@ -147,29 +155,30 @@ private fun SpannedGrid(
check(mainAxisSpacing >= 0.dp) { "Negative columnSpacing $mainAxisSpacing" }
check(crossAxisSpacing >= 0.dp) { "Negative rowSpacing $crossAxisSpacing" }
}
-
- val totalMainAxisGroups: Int =
+ // List of primary axis index to secondary axis index
+ // This is keyed to the size of the spans list for performance reasons as we don't expect the
+ // spans value to change outside of edit mode.
+ val positions = remember(spans.size) { Array(spans.size) { IntIntPair(0, 0) } }
+ val totalMainAxisGroups =
remember(primarySpaces, spans) {
- var currentAccumulated = 0
- var groups = 1
- spans.forEach { span ->
- if (currentAccumulated + span <= primarySpaces) {
- currentAccumulated += span
- } else {
- groups += 1
- currentAccumulated = span
+ var mainAxisGroup = 0
+ var currentSlot = 0
+ spans.fastForEachIndexed { index, span ->
+ if (currentSlot + span > primarySpaces) {
+ currentSlot = 0
+ mainAxisGroup += 1
}
+ positions[index] = IntIntPair(mainAxisGroup, currentSlot)
+ currentSlot += span
}
- groups
+ mainAxisGroup + 1
}
-
val slotPositionsAndSizesCache = remember {
object {
var sizes = IntArray(0)
var positions = IntArray(0)
}
}
-
Layout(
{
(0 until spans.size).map { spanIndex ->
@@ -184,7 +193,13 @@ private fun SpannedGrid(
}
}
) {
- composables(spanIndex)
+ val position = positions[spanIndex]
+ composables(
+ spanIndex,
+ position.second,
+ position.second == 0,
+ positions.getOrNull(spanIndex + 1)?.first != position.first,
+ )
}
}
}
@@ -205,7 +220,6 @@ private fun SpannedGrid(
slotPositionsAndSizesCache.sizes,
)
val cellSizesInCrossAxis = slotPositionsAndSizesCache.sizes
-
// with is needed because of the double receiver (Density, Arrangement).
with(crossAxisArrangement) {
arrange(
@@ -216,68 +230,73 @@ private fun SpannedGrid(
)
}
val startPositions = slotPositionsAndSizesCache.positions
-
val mainAxisSpacingPx = mainAxisSpacing.roundToPx()
val mainAxisTotalGaps = (totalMainAxisGroups - 1) * mainAxisSpacingPx
- val mainAxisSize = if (isVertical) constraints.maxHeight else constraints.maxWidth
+ val mainAxisMaxSize = if (isVertical) constraints.maxHeight else constraints.maxWidth
val mainAxisElementConstraint =
- if (mainAxisSize == Constraints.Infinity) {
+ if (mainAxisMaxSize == Constraints.Infinity) {
Constraints.Infinity
} else {
- max(0, (mainAxisSize - mainAxisTotalGaps) / totalMainAxisGroups)
+ max(0, (mainAxisMaxSize - mainAxisTotalGaps) / totalMainAxisGroups)
}
- val mainAxisSizes = IntArray(totalMainAxisGroups) { 0 }
-
- var currentSlot = 0
- var mainAxisGroup = 0
+ var mainAxisTotalSize = mainAxisTotalGaps
+ var currentMainAxis = 0
+ var currentMainAxisMax = 0
val placeables =
- measurables.mapIndexed { index, measurable ->
+ measurables.fastMapIndexed { index, measurable ->
val span = spans[index]
- if (currentSlot + span > primarySpaces) {
- currentSlot = 0
- mainAxisGroup += 1
- }
+ val position = positions[index]
val crossAxisConstraint =
- calculateWidth(cellSizesInCrossAxis, startPositions, currentSlot, span)
- PlaceResult(
- measurable.measure(
- makeConstraint(
- isVertical,
- mainAxisElementConstraint,
- crossAxisConstraint,
- )
- ),
- currentSlot,
- mainAxisGroup,
+ calculateWidth(cellSizesInCrossAxis, startPositions, position.second, span)
+
+ measurable
+ .measure(
+ makeConstraint(isVertical, mainAxisElementConstraint, crossAxisConstraint)
)
.also {
- currentSlot += span
- mainAxisSizes[mainAxisGroup] =
- max(
- mainAxisSizes[mainAxisGroup],
- if (isVertical) it.placeable.height else it.placeable.width,
- )
+ val placeableSize = if (isVertical) it.height else it.width
+ if (position.first != currentMainAxis) {
+ // New row -- Add the max size to the total and reset the max
+ mainAxisTotalSize += currentMainAxisMax
+ currentMainAxisMax = placeableSize
+ currentMainAxis = position.first
+ } else {
+ currentMainAxisMax = max(currentMainAxisMax, placeableSize)
+ }
}
}
+ mainAxisTotalSize += currentMainAxisMax
- val mainAxisTotalSize = mainAxisTotalGaps + mainAxisSizes.sum()
- val mainAxisStartingPoints =
- mainAxisSizes.runningFold(0) { acc, value -> acc + value + mainAxisSpacingPx }
val height = if (isVertical) mainAxisTotalSize else crossAxisSize
val width = if (isVertical) crossAxisSize else mainAxisTotalSize
layout(width, height) {
- placeables.forEach { (placeable, slot, mainAxisGroup) ->
+ var previousMainAxis = 0
+ var currentMainAxisPosition = 0
+ var currentMainAxisMax = 0
+ placeables.forEachIndexed { index, placeable ->
+ val slot = positions[index].second
+ val mainAxisSize = if (isVertical) placeable.height else placeable.width
+
+ if (positions[index].first != previousMainAxis) {
+ // Move up a row + padding
+ currentMainAxisPosition += currentMainAxisMax + mainAxisSpacingPx
+ currentMainAxisMax = mainAxisSize
+ previousMainAxis = positions[index].first
+ } else {
+ currentMainAxisMax = max(currentMainAxisMax, mainAxisSize)
+ }
+
val x =
if (isVertical) {
startPositions[slot]
} else {
- mainAxisStartingPoints[mainAxisGroup]
+ currentMainAxisPosition
}
val y =
if (isVertical) {
- mainAxisStartingPoints[mainAxisGroup]
+ currentMainAxisPosition
} else {
startPositions[slot]
}
@@ -321,9 +340,3 @@ private fun calculateCellsCrossAxisSize(
outArray[index] = slotSize + if (index < remainingPixels) 1 else 0
}
}
-
-private data class PlaceResult(
- val placeable: Placeable,
- val slotIndex: Int,
- val mainAxisGroup: Int,
-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt
index 40010548a268..c088900f9304 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModel.kt
@@ -17,33 +17,39 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.Flags
+import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.FromGlanceableHubTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.BlurConfig
import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
+@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class GlanceableHubToPrimaryBouncerTransitionViewModel
@Inject
constructor(
private val blurConfig: BlurConfig,
animationFlow: KeyguardTransitionAnimationFlow,
- communalSettingsInteractor: CommunalSettingsInteractor,
+ private val communalSettingsInteractor: CommunalSettingsInteractor,
+ private val communalSceneInteractor: CommunalSceneInteractor,
+ private val keyguardStateController: KeyguardStateController,
) : PrimaryBouncerTransition {
private val transitionAnimation =
animationFlow
.setup(
- duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
+ duration = FromGlanceableHubTransitionInteractor.TO_BOUNCER_DURATION,
edge = Edge.INVALID,
)
.setupWithoutSceneContainer(edge = Edge.create(GLANCEABLE_HUB, PRIMARY_BOUNCER))
@@ -59,6 +65,13 @@ constructor(
transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
}
+ /** Whether to delay the animation to fade in bouncer elements. */
+ fun willDelayAppearAnimation(isLandscape: Boolean): Boolean =
+ communalSettingsInteractor.isV2FlagEnabled() &&
+ communalSceneInteractor.isIdleOnCommunal.value &&
+ !keyguardStateController.isKeyguardScreenRotationAllowed() &&
+ isLandscape
+
override val notificationBlurRadius: Flow<Float> =
transitionAnimation.immediatelyTransitionTo(0.0f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt
index 9b443f56636a..5d62c022efba 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt
@@ -90,15 +90,16 @@ constructor(@MediaCarouselControllerLog private val buffer: LogBuffer) {
fun logCarouselVisible() = buffer.log(TAG, LogLevel.DEBUG, {}, { "showing carousel" })
- fun logMediaHostVisibility(location: Int, visible: Boolean) {
+ fun logMediaHostVisibility(location: Int, visible: Boolean, oldState: Boolean) {
buffer.log(
TAG,
LogLevel.DEBUG,
{
int1 = location
bool1 = visible
+ bool2 = oldState
},
- { "media host visibility changed location=$location, visible:$visible" },
+ { "media host visibility changed location=$location, visible:$visible, was:$oldState" },
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index c6894082f1c8..69006c6107cc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -1129,10 +1129,11 @@ constructor(
traceSection("MediaHierarchyManager#updateHostAttachment") {
if (SceneContainerFlag.isEnabled) {
// No need to manage transition states - just update the desired location directly
- logger.logMediaHostAttachment(desiredLocation)
+ val host = getHost(desiredLocation)
+ logger.logMediaHostAttachment(desiredLocation, host?.visible)
mediaCarouselController.onDesiredLocationChanged(
desiredLocation = desiredLocation,
- desiredHostState = getHost(desiredLocation),
+ desiredHostState = host,
animate = false,
)
return
@@ -1169,7 +1170,8 @@ constructor(
// that and directly set the mediaFrame's bounds within the premeasured host.
targetHost.addView(mediaFrame)
}
- logger.logMediaHostAttachment(currentAttachmentLocation)
+ val host = getHost(currentAttachmentLocation)
+ logger.logMediaHostAttachment(currentAttachmentLocation, host?.visible)
if (isCrossFadeAnimatorRunning) {
// When cross-fading with an animation, we only notify the media carousel of the
// location change, once the view is reattached to the new place and not
@@ -1313,6 +1315,7 @@ constructor(
isHomeScreenShadeVisibleToUser() ||
isGlanceableHubVisibleToUser()
val mediaVisible = qsExpanded || hasActiveMediaOrRecommendation
+ logger.logUserVisibilityChange(shadeVisible, mediaVisible)
mediaCarouselController.mediaCarouselScrollHandler.visibleToUser =
shadeVisible && mediaVisible
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt
index 1514db38d882..089d16b98de8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt
@@ -36,7 +36,7 @@ class MediaViewLogger @Inject constructor(@MediaViewLog private val buffer: LogB
int1 = width
int2 = height
},
- { "size ($str1): $int1 x $int2" }
+ { "size ($str1): $int1 x $int2" },
)
}
@@ -49,11 +49,31 @@ class MediaViewLogger @Inject constructor(@MediaViewLog private val buffer: LogB
int1 = startLocation
int2 = endLocation
},
- { "location ($str1): $int1 -> $int2" }
+ { "location ($str1): $int1 -> $int2" },
)
}
- fun logMediaHostAttachment(host: Int) {
- buffer.log(TAG, LogLevel.DEBUG, { int1 = host }, { "Host (updateHostAttachment): $int1" })
+ fun logMediaHostAttachment(host: Int, visible: Boolean?) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ int1 = host
+ str1 = visible.toString()
+ },
+ { "Host (updateHostAttachment): $int1 visible $str1" },
+ )
+ }
+
+ fun logUserVisibilityChange(shadeVisible: Boolean, mediaVisible: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ bool1 = shadeVisible
+ bool2 = mediaVisible
+ },
+ { "User visibility shade: $shadeVisible media: $mediaVisible" },
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt
index 11251cdb6315..a518349ea424 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt
@@ -208,6 +208,7 @@ class MediaHost(
* the visibility has changed
*/
fun updateViewVisibility() {
+ val oldState = state.visible
state.visible =
if (mediaCarouselController.isLockedAndHidden()) {
false
@@ -217,9 +218,9 @@ class MediaHost(
mediaDataManager.hasAnyMediaOrRecommendation()
}
val newVisibility = if (visible) View.VISIBLE else View.GONE
- if (newVisibility != hostView.visibility) {
+ if (oldState != state.visible || newVisibility != hostView.visibility) {
hostView.visibility = newVisibility
- debugLogger.logMediaHostVisibility(location, visible)
+ debugLogger.logMediaHostVisibility(location, visible, oldState)
visibleChangedListeners.forEach { it.invoke(visible) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
index eb6f97942ec0..b80e6b403cf3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
@@ -35,11 +35,16 @@ fun List<BounceableTileViewModel>.bounceableInfo(
index: Int,
column: Int,
columns: Int,
+ isFirstInRow: Boolean,
+ isLastInRow: Boolean,
): BounceableInfo {
- // Only look for neighbor bounceables if they are on the same row
+ // A tile may be the last in the row without being on the last column
val onLastColumn = sizedTile.onLastColumn(column, columns)
- val previousTile = getOrNull(index - 1)?.takeIf { column != 0 }
- val nextTile = getOrNull(index + 1)?.takeIf { !onLastColumn }
+
+ // Only look for neighbor bounceables if they are on the same row
+ val previousTile = getOrNull(index - 1)?.takeIf { !isFirstInRow }
+ val nextTile = getOrNull(index + 1)?.takeIf { !isLastInRow }
+
return BounceableInfo(this[index], previousTile, nextTile, !onLastColumn)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
index 495870f0a978..cdc03bb9be35 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
@@ -57,7 +57,6 @@ fun ContentScope.QuickQuickSettings(
onDispose { tiles.forEach { it.stopListening(token) } }
}
val columns = viewModel.columns
- var cellIndex = 0
Box(modifier = modifier) {
GridAnchor()
VerticalSpannedGrid(
@@ -67,17 +66,23 @@ fun ContentScope.QuickQuickSettings(
spans = spans,
modifier = Modifier.sysuiResTag("qqs_tile_layout"),
keys = { sizedTiles[it].tile.spec },
- ) { spanIndex ->
+ ) { spanIndex, column, isFirstInColumn, isLastInColumn ->
val it = sizedTiles[spanIndex]
- val column = cellIndex % columns
- cellIndex += it.width
Element(it.tile.spec.toElementKey(spanIndex), Modifier) {
Tile(
tile = it.tile,
iconOnly = it.isIcon,
squishiness = { squishiness },
coroutineScope = scope,
- bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+ bounceableInfo =
+ bounceables.bounceableInfo(
+ it,
+ index = spanIndex,
+ column = column,
+ columns = columns,
+ isFirstInRow = isFirstInColumn,
+ isLastInRow = isLastInColumn,
+ ),
tileHapticsViewModelFactoryProvider =
viewModel.tileHapticsViewModelFactoryProvider,
// There should be no QuickQuickSettings when the details view is enabled.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
index dfee497655d1..0503049382a8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
@@ -85,8 +85,6 @@ constructor(
remember(sizedTiles) { List(sizedTiles.size) { BounceableTileViewModel() } }
val squishiness by viewModel.squishinessViewModel.squishiness.collectAsStateWithLifecycle()
val scope = rememberCoroutineScope()
- var cellIndex = 0
-
val spans by remember(sizedTiles) { derivedStateOf { sizedTiles.fastMap { it.width } } }
VerticalSpannedGrid(
@@ -95,10 +93,9 @@ constructor(
rowSpacing = dimensionResource(R.dimen.qs_tile_margin_vertical),
spans = spans,
keys = { sizedTiles[it].tile.spec },
- ) { spanIndex ->
+ ) { spanIndex, column, isFirstInColumn, isLastInColumn ->
val it = sizedTiles[spanIndex]
- val column = cellIndex % columns
- cellIndex += it.width
+
Element(it.tile.spec.toElementKey(spanIndex), Modifier) {
Tile(
tile = it.tile,
@@ -106,7 +103,15 @@ constructor(
squishiness = { squishiness },
tileHapticsViewModelFactoryProvider = tileHapticsViewModelFactoryProvider,
coroutineScope = scope,
- bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+ bounceableInfo =
+ bounceables.bounceableInfo(
+ it,
+ index = spanIndex,
+ column = column,
+ columns = columns,
+ isFirstInRow = isFirstInColumn,
+ isLastInRow = isLastInColumn,
+ ),
detailsViewModel = detailsViewModel,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index e4cd7ea098af..305444f7ab5e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -451,6 +451,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
} else {
mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
}
+ } else if (state.glanceableHubOrientationAware) {
+ mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
} else {
mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
@@ -627,6 +629,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
state.shadeOrQsExpanded,
state.notificationShadeFocusable,
state.glanceableHubShowing,
+ state.glanceableHubOrientationAware,
state.bouncerShowing,
state.keyguardFadingAway,
state.keyguardGoingAway,
@@ -763,6 +766,12 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
}
@Override
+ public void setGlanceableHubOrientationAware(boolean isOrientationAware) {
+ mCurrentState.glanceableHubOrientationAware = isOrientationAware;
+ apply(mCurrentState);
+ }
+
+ @Override
public void setBackdropShowing(boolean showing) {
mCurrentState.mediaBackdropShowing = showing;
apply(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
index 6a4b52af498c..a1eac745b3a1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
@@ -36,6 +36,7 @@ class NotificationShadeWindowState(
@JvmField var notificationShadeFocusable: Boolean = false,
@JvmField var bouncerShowing: Boolean = false,
@JvmField var glanceableHubShowing: Boolean = false,
+ @JvmField var glanceableHubOrientationAware: Boolean = false,
@JvmField var keyguardFadingAway: Boolean = false,
@JvmField var keyguardGoingAway: Boolean = false,
@JvmField var qsExpanded: Boolean = false,
@@ -81,6 +82,7 @@ class NotificationShadeWindowState(
notificationShadeFocusable.toString(),
bouncerShowing.toString(),
glanceableHubShowing.toString(),
+ glanceableHubOrientationAware.toString(),
keyguardFadingAway.toString(),
keyguardGoingAway.toString(),
qsExpanded.toString(),
@@ -122,6 +124,7 @@ class NotificationShadeWindowState(
panelExpanded: Boolean,
notificationShadeFocusable: Boolean,
glanceableHubShowing: Boolean,
+ glanceableHubOrientationAware: Boolean,
bouncerShowing: Boolean,
keyguardFadingAway: Boolean,
keyguardGoingAway: Boolean,
@@ -153,6 +156,7 @@ class NotificationShadeWindowState(
this.shadeOrQsExpanded = panelExpanded
this.notificationShadeFocusable = notificationShadeFocusable
this.glanceableHubShowing = glanceableHubShowing
+ this.glanceableHubOrientationAware = glanceableHubOrientationAware
this.bouncerShowing = bouncerShowing
this.keyguardFadingAway = keyguardFadingAway
this.keyguardGoingAway = keyguardGoingAway
@@ -202,6 +206,7 @@ class NotificationShadeWindowState(
"panelExpanded",
"notificationShadeFocusable",
"glanceableHubShowing",
+ "glanceableHubOrientationAware",
"bouncerShowing",
"keyguardFadingAway",
"keyguardGoingAway",
@@ -223,7 +228,7 @@ class NotificationShadeWindowState(
"dozing",
"scrimsVisibility",
"backgroundBlurRadius",
- "communalVisible"
+ "communalVisible",
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
index 4bb12e59a877..6ebe02469f5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
@@ -57,6 +57,12 @@ public class NotificationGroupingUtil {
private static final VisibilityApplicator VISIBILITY_APPLICATOR = new VisibilityApplicator();
private static final VisibilityApplicator APP_NAME_APPLICATOR = new AppNameApplicator();
private static final ResultApplicator LEFT_ICON_APPLICATOR = new LeftIconApplicator();
+ private static final DataExtractor ICON_EXTRACTOR = new DataExtractor() {
+ @Override
+ public Object extractData(ExpandableNotificationRow row) {
+ return row.getEntry().getSbn().getNotification();
+ }
+ };
private final ExpandableNotificationRow mRow;
private final ArrayList<Processor> mProcessors = new ArrayList<>();
@@ -103,26 +109,31 @@ public class NotificationGroupingUtil {
// To hide the icons if they are the same and the color is the same
mProcessors.add(new Processor(mRow,
com.android.internal.R.id.icon,
+ ICON_EXTRACTOR,
iconVisibilityComparator,
VISIBILITY_APPLICATOR));
// To grey out the icons when they are not the same, or they have the same color
mProcessors.add(new Processor(mRow,
com.android.internal.R.id.status_bar_latest_event_content,
+ ICON_EXTRACTOR,
greyComparator,
greyApplicator));
// To show the large icon on the left side instead if all the small icons are the same
mProcessors.add(new Processor(mRow,
com.android.internal.R.id.status_bar_latest_event_content,
+ ICON_EXTRACTOR,
iconVisibilityComparator,
LEFT_ICON_APPLICATOR));
// To only show the work profile icon in the group header
mProcessors.add(new Processor(mRow,
com.android.internal.R.id.profile_badge,
+ null /* Extractor */,
BADGE_COMPARATOR,
VISIBILITY_APPLICATOR));
// To hide the app name in group children
mProcessors.add(new Processor(mRow,
com.android.internal.R.id.app_name_text,
+ null,
APP_NAME_COMPARATOR,
APP_NAME_APPLICATOR));
// To hide the header text if it's the same
@@ -242,20 +253,23 @@ public class NotificationGroupingUtil {
private static class Processor {
private final int mId;
+ private final DataExtractor mExtractor;
private final ViewComparator mComparator;
private final ResultApplicator mApplicator;
private final ExpandableNotificationRow mParentRow;
private boolean mApply;
private View mParentView;
+ private Object mParentData;
public static Processor forTextView(ExpandableNotificationRow row, int id) {
- return new Processor(row, id, TEXT_VIEW_COMPARATOR, VISIBILITY_APPLICATOR);
+ return new Processor(row, id, null, TEXT_VIEW_COMPARATOR, VISIBILITY_APPLICATOR);
}
- Processor(ExpandableNotificationRow row, int id,
+ Processor(ExpandableNotificationRow row, int id, DataExtractor extractor,
ViewComparator comparator,
ResultApplicator applicator) {
mId = id;
+ mExtractor = extractor;
mApplicator = applicator;
mComparator = comparator;
mParentRow = row;
@@ -265,6 +279,7 @@ public class NotificationGroupingUtil {
NotificationViewWrapper wrapper = mParentRow.getNotificationViewWrapper();
View header = wrapper == null ? null : wrapper.getNotificationHeader();
mParentView = header == null ? null : header.findViewById(mId);
+ mParentData = mExtractor == null ? null : mExtractor.extractData(mParentRow);
mApply = !mComparator.isEmpty(mParentView);
}
@@ -282,7 +297,9 @@ public class NotificationGroupingUtil {
// when for example showing an undo notification
return;
}
- mApply = mComparator.compare(mParentView, ownView);
+ Object childData = mExtractor == null ? null : mExtractor.extractData(row);
+ mApply = mComparator.compare(mParentView, ownView,
+ mParentData, childData);
}
public void apply(ExpandableNotificationRow row) {
@@ -314,9 +331,11 @@ public class NotificationGroupingUtil {
/**
* @param parent the view with the given id in the group header
* @param child the view with the given id in the child notification
+ * @param parentData optional data for the parent
+ * @param childData optional data for the child
* @return whether to views are the same
*/
- boolean compare(View parent, View child);
+ boolean compare(View parent, View child, Object parentData, Object childData);
boolean isEmpty(View view);
}
@@ -327,7 +346,7 @@ public class NotificationGroupingUtil {
private static class BadgeComparator implements ViewComparator {
@Override
- public boolean compare(View parent, View child) {
+ public boolean compare(View parent, View child, Object parentData, Object childData) {
return parent.getVisibility() != View.GONE;
}
@@ -345,7 +364,7 @@ public class NotificationGroupingUtil {
private static class TextViewComparator implements ViewComparator {
@Override
- public boolean compare(View parent, View child) {
+ public boolean compare(View parent, View child, Object parentData, Object childData) {
TextView parentView = (TextView) parent;
CharSequence parentText = parentView == null ? "" : parentView.getText();
TextView childView = (TextView) child;
@@ -361,7 +380,7 @@ public class NotificationGroupingUtil {
private abstract static class IconComparator implements ViewComparator {
@Override
- public boolean compare(View parent, View child) {
+ public boolean compare(View parent, View child, Object parentData, Object childData) {
return false;
}
@@ -421,14 +440,14 @@ public class NotificationGroupingUtil {
private static class AppNameComparator extends TextViewComparator {
@Override
- public boolean compare(View parent, View child) {
+ public boolean compare(View parent, View child, Object parentData, Object childData) {
if (isEmpty(child)) {
// In headerless notifications the AppName view exists but is usually GONE (and not
// populated). We need to treat this case as equal to the header in order to
// deduplicate the view.
return true;
}
- return super.compare(parent, child);
+ return super.compare(parent, child, parentData, childData);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
index 85fad420daf1..50cf015af5e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
@@ -89,6 +89,9 @@ public interface NotificationShadeWindowController extends RemoteInputController
/** Sets the state of whether the glanceable hub is showing or not. */
default void setGlanceableHubShowing(boolean showing) {}
+ /** Sets the state of whether the glanceable hub can change with user's orientation or not. */
+ default void setGlanceableHubOrientationAware(boolean isOrientationAware) {}
+
/** Sets the state of whether the backdrop is showing or not. */
default void setBackdropShowing(boolean showing) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index f52b9247f6cc..df8fb5e75368 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -91,7 +91,7 @@ constructor(
ImageSpan(it, ImageSpan.ALIGN_CENTER)
}
val decoratedSummary =
- SpannableString("x" + entry.ranking.summarization).apply {
+ SpannableString("x " + entry.ranking.summarization).apply {
setSpan(
/* what = */ imageSpan,
/* start = */ 0,
@@ -100,9 +100,9 @@ constructor(
)
entry.ranking.summarization?.let {
setSpan(
- /* what = */ StyleSpan(Typeface.BOLD),
- /* start = */ 1,
- /* end = */ it.length,
+ /* what = */ StyleSpan(Typeface.ITALIC),
+ /* start = */ 2,
+ /* end = */ it.length + 2,
/* flags = */ Spanned.SPAN_EXCLUSIVE_INCLUSIVE,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
index 74faf2576abd..0a24d7a71ce9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
@@ -15,12 +15,12 @@
*/
package com.android.systemui.statusbar.notification
+import android.util.FloatProperty
import android.util.Property
import android.view.View
-import androidx.dynamicanimation.animation.DynamicAnimation
-import androidx.dynamicanimation.animation.FloatPropertyCompat
-import androidx.dynamicanimation.animation.SpringAnimation
-import androidx.dynamicanimation.animation.SpringForce
+import com.android.internal.dynamicanimation.animation.DynamicAnimation
+import com.android.internal.dynamicanimation.animation.SpringAnimation
+import com.android.internal.dynamicanimation.animation.SpringForce
import com.android.systemui.res.R
import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.createDefaultSpring
import com.android.systemui.statusbar.notification.stack.AnimationProperties
@@ -33,8 +33,8 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties
*/
data class PhysicsProperty(val tag: Int, val property: Property<View, Float>) {
val offsetProperty =
- object : FloatPropertyCompat<View>(property.name) {
- override fun getValue(view: View): Float {
+ object : FloatProperty<View>(property.name) {
+ override fun get(view: View): Float {
return property.get(view)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index 248b5286803f..28923b0ab71e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator
+import android.app.NotificationChannel.SYSTEM_RESERVED_IDS
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
@@ -89,6 +90,7 @@ class ConversationCoordinator @Inject constructor(
object : NotifSectioner("Priority People", BUCKET_PRIORITY_PEOPLE) {
override fun isInSection(entry: PipelineEntry): Boolean {
return getPeopleType(entry) == TYPE_IMPORTANT_PERSON
+ && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
}
}
@@ -96,10 +98,12 @@ class ConversationCoordinator @Inject constructor(
val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) {
override fun isInSection(entry: PipelineEntry): Boolean {
if (SortBySectionTimeFlag.isEnabled) {
- return highPriorityProvider.isHighPriorityConversation(entry)
- || isConversation(entry)
+ return (highPriorityProvider.isHighPriorityConversation(entry)
+ || isConversation(entry))
+ && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
} else {
return highPriorityProvider.isHighPriorityConversation(entry)
+ && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
}
}
@@ -111,11 +115,12 @@ class ConversationCoordinator @Inject constructor(
}
val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) {
- // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting.
- // All remaining conversations must be silent.
+ // Because the peopleAlertingSectioner is above this one, it will claim all conversations
+ // that are alerting. All remaining conversations must be silent.
override fun isInSection(entry: PipelineEntry): Boolean {
SortBySectionTimeFlag.assertInLegacyMode()
return isConversation(entry)
+ && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
}
override fun getComparator(): NotifComparator {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
index 7959e99f3189..2a01a14f56aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
@@ -20,6 +20,7 @@ import android.app.Flags
import android.app.Flags.notificationsRedesignTemplates
import android.app.Notification
import android.graphics.PorterDuff
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
@@ -80,9 +81,13 @@ fun AODPromotedNotification(
val content = viewModel.content ?: return
val audiblyAlertedIconVisible = viewModel.audiblyAlertedIconVisible
- key(content.identity) {
- val layoutResource = content.layoutResource ?: return
+ val layoutResource = content.layoutResource
+ if (layoutResource == null) {
+ Log.w(TAG, "not displaying promoted notif with ineligible style on AOD")
+ return
+ }
+ key(content.identity) {
val sidePaddings = dimensionResource(systemuiR.dimen.notification_side_paddings)
val sidePaddingValues = PaddingValues(horizontal = sidePaddings, vertical = 0.dp)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index a081ad5bb82c..6837cb2a6292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -119,6 +119,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
protected Point mTargetPoint;
private boolean mDismissed;
private boolean mRefocusOnDismiss;
+ protected boolean mIsBlurSupported;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -128,12 +129,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
private void updateColors() {
- if (notificationRowTransparency()) {
+ if (usesTransparentBackground()) {
mNormalColor = SurfaceEffectColors.surfaceEffect1(getContext());
} else {
mNormalColor = mContext.getColor(
com.android.internal.R.color.materialColorSurfaceContainerHigh);
}
+ setBackgroundToNormalColor();
mTintedRippleColor = mContext.getColor(
R.color.notification_ripple_tinted_color);
mNormalRippleColor = mContext.getColor(
@@ -144,6 +146,12 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mOverrideAmount = 0.0f;
}
+ private void setBackgroundToNormalColor() {
+ if (mBackgroundNormal != null) {
+ mBackgroundNormal.setNormalColor(mNormalColor);
+ }
+ }
+
/**
* Reload background colors from resources and invalidate views.
*/
@@ -173,6 +181,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundNormal = findViewById(R.id.backgroundNormal);
mFakeShadow = findViewById(R.id.fake_shadow);
mShadowHidden = mFakeShadow.getVisibility() != VISIBLE;
+ setBackgroundToNormalColor();
initBackground();
updateBackgroundTint();
updateOutlineAlpha();
@@ -326,6 +335,21 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundNormal.setBottomAmountClips(!isChildInGroup());
}
+ public void setIsBlurSupported(boolean isBlurSupported) {
+ if (!notificationRowTransparency()) {
+ return;
+ }
+ boolean usedTransparentBackground = usesTransparentBackground();
+ mIsBlurSupported = isBlurSupported;
+ if (usedTransparentBackground != usesTransparentBackground()) {
+ updateBackgroundColors();
+ }
+ }
+
+ protected boolean usesTransparentBackground() {
+ return mIsBlurSupported && notificationRowTransparency();
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 179951f67902..3ef1fd2275a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -20,8 +20,8 @@ import static android.app.Flags.notificationsRedesignTemplates;
import static android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
-import static com.android.systemui.Flags.notificationsPinnedHunInShade;
import static com.android.systemui.Flags.notificationRowTransparency;
+import static com.android.systemui.Flags.notificationsPinnedHunInShade;
import static com.android.systemui.flags.Flags.ENABLE_NOTIFICATIONS_SIMULATE_SLOW_MEASURE;
import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
@@ -1678,14 +1678,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
if (view != null) {
view.setBackgroundTintColor(color);
}
- if (notificationRowTransparency()
- && (mBackgroundNormal != null)) {
+ if (notificationRowTransparency() && mBackgroundNormal != null) {
if (NotificationBundleUi.isEnabled()) {
- mBackgroundNormal.setBgIsColorized(mEntryAdapter.isColorized());
+ mBackgroundNormal.setBgIsColorized(
+ usesTransparentBackground() && mEntryAdapter.isColorized());
} else {
if (mEntry != null) {
mBackgroundNormal.setBgIsColorized(
- mEntry.getSbn().getNotification().isColorized());
+ usesTransparentBackground()
+ && mEntry.getSbn().getNotification().isColorized());
}
}
}
@@ -3021,6 +3022,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mUserLocked = userLocked;
mPrivateLayout.setUserExpanding(userLocked);
+ mPublicLayout.setUserExpanding(userLocked);
// This is intentionally not guarded with mIsSummaryWithChildren since we might have had
// children but not anymore.
if (mChildrenContainer != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
index 344d0f6d3741..ba80f016cad4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
@@ -51,6 +51,7 @@ import java.util.Objects;
*/
public class HybridConversationNotificationView extends HybridNotificationView {
+ private static final int MAX_SUMMARIZATION_LINES = 2;
private ImageView mConversationIconView;
private TextView mConversationSenderName;
private ViewStub mConversationFacePileStub;
@@ -292,11 +293,14 @@ public class HybridConversationNotificationView extends HybridNotificationView {
@Nullable CharSequence summarization
) {
if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return;
- if (summarization != null) {
+ if (!TextUtils.isEmpty(summarization)) {
mConversationSenderName.setVisibility(GONE);
titleText = null;
contentText = summarization;
+ mTextView.setSingleLine(false);
+ mTextView.setMaxLines(MAX_SUMMARIZATION_LINES);
} else {
+ mTextView.setSingleLine(true);
if (conversationSenderName == null) {
mConversationSenderName.setVisibility(GONE);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 4978fa4880aa..e1219e88a405 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -73,7 +73,7 @@ public class NotificationBackgroundView extends View implements Dumpable,
private int mDrawableAlpha = 255;
private final ColorStateList mLightColoredStatefulColors;
private final ColorStateList mDarkColoredStatefulColors;
- private final int mNormalColor;
+ private int mNormalColor;
private boolean mBgIsColorized = false;
private boolean mForceOpaque = false;
private final int convexR = 9;
@@ -89,15 +89,13 @@ public class NotificationBackgroundView extends View implements Dumpable,
R.color.notification_state_color_light);
mDarkColoredStatefulColors = getResources().getColorStateList(
R.color.notification_state_color_dark);
- if (notificationRowTransparency()) {
- mNormalColor = SurfaceEffectColors.surfaceEffect1(getContext());
- } else {
- mNormalColor = mContext.getColor(
- com.android.internal.R.color.materialColorSurfaceContainerHigh);
- }
mFocusOverlayStroke = getResources().getDimension(R.dimen.notification_focus_stroke_width);
}
+ public void setNormalColor(int color) {
+ mNormalColor = color;
+ }
+
@Override
public void onTargetVisibilityChanged(boolean targetVisible) {
if (NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
index f0b5c3667962..8984f2c4220d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
@@ -50,6 +50,15 @@ object ActivatableNotificationViewBinder {
view.registerListenersWhileAttached(touchHandler)
}
}
+ view.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ launch {
+ viewModel.isBlurSupported.collect { supported ->
+ view.setIsBlurSupported(supported)
+ }
+ }
+ }
+ }
}
private suspend fun ActivatableNotificationView.registerListenersWhileAttached(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt
index f46d42473863..9a86ffbe33b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.row.ui.viewmodel
import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
+import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.flow.Flow
@@ -26,25 +27,34 @@ import kotlinx.coroutines.flow.map
interface ActivatableNotificationViewModel : ExpandableOutlineViewModel {
/** Does the view react to touches? */
val isTouchable: Flow<Boolean>
+ val isBlurSupported: Flow<Boolean>
companion object {
operator fun invoke(
a11yInteractor: AccessibilityInteractor,
- ): ActivatableNotificationViewModel = ActivatableNotificationViewModelImpl(a11yInteractor)
+ windowRootViewBlurInteractor: WindowRootViewBlurInteractor
+ ): ActivatableNotificationViewModel =
+ ActivatableNotificationViewModelImpl(a11yInteractor, windowRootViewBlurInteractor)
}
}
private class ActivatableNotificationViewModelImpl(
a11yInteractor: AccessibilityInteractor,
+ windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
) : ActivatableNotificationViewModel {
override val isTouchable: Flow<Boolean> =
// If a11y touch exploration is enabled, then the activatable view should ignore touches
a11yInteractor.isTouchExplorationEnabled.map { !it }
+ override val isBlurSupported: Flow<Boolean> =
+ windowRootViewBlurInteractor.isBlurCurrentlySupported
}
@Module
object ActivatableNotificationViewModelModule {
@Provides
- fun provideViewModel(interactor: AccessibilityInteractor) =
- ActivatableNotificationViewModel(interactor)
+ fun provideViewModel(
+ a11yInteractor: AccessibilityInteractor,
+ windowRootViewBlurInteractor: WindowRootViewBlurInteractor
+ ) =
+ ActivatableNotificationViewModel(a11yInteractor, windowRootViewBlurInteractor)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
index 3d60092cf29a..4d01cbd19253 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
@@ -23,7 +23,7 @@ import android.util.Property;
import android.view.View;
import android.view.animation.Interpolator;
-import androidx.dynamicanimation.animation.DynamicAnimation;
+import com.android.internal.dynamicanimation.animation.DynamicAnimation;
import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 9a5cf9ceed53..19abfa8140df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -32,10 +32,9 @@ import android.content.Context;
import android.util.Property;
import android.view.View;
-import androidx.dynamicanimation.animation.DynamicAnimation;
-
import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.dynamicanimation.animation.DynamicAnimation;
import com.android.systemui.res.R;
import com.android.systemui.shared.clocks.AnimatableClockView;
import com.android.systemui.statusbar.NotificationShelf;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index 2ef6f362af34..29dbeb2c8ee4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -30,10 +30,9 @@ import android.util.Property;
import android.view.View;
import android.view.animation.Interpolator;
-import androidx.dynamicanimation.animation.DynamicAnimation;
-import androidx.dynamicanimation.animation.SpringAnimation;
-
import com.android.app.animation.Interpolators;
+import com.android.internal.dynamicanimation.animation.DynamicAnimation;
+import com.android.internal.dynamicanimation.animation.SpringAnimation;
import com.android.systemui.Dumpable;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.AnimatableProperty;
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt
deleted file mode 100644
index 43d3eb7b857a..000000000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt
+++ /dev/null
@@ -1,39 +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.communal.ui.viewmodel
-
-import android.service.dream.dreamManager
-import com.android.internal.logging.uiEventLogger
-import com.android.systemui.communal.domain.interactor.communalPrefsInteractor
-import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.plugins.activityStarter
-import com.android.systemui.statusbar.policy.batteryController
-
-val Kosmos.communalToDreamButtonViewModel by
- Kosmos.Fixture {
- CommunalToDreamButtonViewModel(
- backgroundContext = testDispatcher,
- batteryController = batteryController,
- prefsInteractor = communalPrefsInteractor,
- settingsInteractor = communalSettingsInteractor,
- activityStarter = activityStarter,
- dreamManager = dreamManager,
- uiEventLogger = uiEventLogger,
- )
- }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt
index b233d3ff9e0f..c6f55f053d35 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToPrimaryBouncerTransitionViewModelKosmos.kt
@@ -16,16 +16,20 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.transitions.blurConfig
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.statusbar.policy.keyguardStateController
val Kosmos.glanceableHubToPrimaryBouncerTransitionViewModel by Fixture {
GlanceableHubToPrimaryBouncerTransitionViewModel(
animationFlow = keyguardTransitionAnimationFlow,
blurConfig = blurConfig,
communalSettingsInteractor = communalSettingsInteractor,
+ communalSceneInteractor = communalSceneInteractor,
+ keyguardStateController = keyguardStateController,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 02cf1f5a7214..dff9f3abfc05 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -29,6 +29,7 @@ import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.communal.domain.interactor.communalSceneInteractor
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.communal.ui.viewmodel.communalTransitionViewModel
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
@@ -87,6 +88,7 @@ import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.wifiIntera
import com.android.systemui.statusbar.policy.configurationController
import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
+import com.android.systemui.statusbar.policy.keyguardStateController
import com.android.systemui.statusbar.ui.viewmodel.keyguardStatusBarViewModel
import com.android.systemui.util.time.systemClock
import com.android.systemui.volume.domain.interactor.volumeDialogInteractor
@@ -126,6 +128,7 @@ class KosmosJavaAdapter() {
val keyguardInteractor by lazy { kosmos.keyguardInteractor }
val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
val keyguardTransitionInteractor by lazy { kosmos.keyguardTransitionInteractor }
+ val keyguardStateController by lazy { kosmos.keyguardStateController }
val keyguardStatusBarViewModel by lazy { kosmos.keyguardStatusBarViewModel }
val powerRepository by lazy { kosmos.fakePowerRepository }
val clock by lazy { kosmos.systemClock }
@@ -147,6 +150,7 @@ class KosmosJavaAdapter() {
val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
val communalInteractor by lazy { kosmos.communalInteractor }
val communalSceneInteractor by lazy { kosmos.communalSceneInteractor }
+ val communalSettingsInteractor by lazy { kosmos.communalSettingsInteractor }
val sceneContainerPlugin by lazy { kosmos.sceneContainerPlugin }
val deviceProvisioningInteractor by lazy { kosmos.deviceProvisioningInteractor }
val fakeDeviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt
index 2523975c182c..7ccbdb79101c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt
@@ -19,9 +19,11 @@ package com.android.systemui.statusbar.notification.row.ui.viewmodel
import com.android.systemui.accessibility.domain.interactor.accessibilityInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
val Kosmos.activatableNotificationViewModel by Fixture {
ActivatableNotificationViewModel.invoke(
a11yInteractor = accessibilityInteractor,
+ windowRootViewBlurInteractor = windowRootViewBlurInteractor,
)
}
diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS
index 7009282b66e1..169f887ede56 100644
--- a/proto/src/metrics_constants/OWNERS
+++ b/proto/src/metrics_constants/OWNERS
@@ -1,4 +1,2 @@
cwren@android.com
-yanglu@google.com
yaochen@google.com
-yro@google.com
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java
index db3cd8ed712f..1153a77d5c9a 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java
@@ -35,14 +35,4 @@ import java.lang.annotation.Target;
@Retention(SOURCE)
@Target({FIELD, METHOD, PARAMETER, TYPE_USE})
@libcore.api.IntraCoreApi
-public @interface NonNull {
- /**
- * Min Android API level (inclusive) to which this annotation is applied.
- */
- int from() default Integer.MIN_VALUE;
-
- /**
- * Max Android API level to which this annotation is applied.
- */
- int to() default Integer.MAX_VALUE;
-}
+public @interface NonNull {}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java
index 3371978b0568..295f083426ff 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java
@@ -35,14 +35,4 @@ import java.lang.annotation.Target;
@Retention(SOURCE)
@Target({FIELD, METHOD, PARAMETER, TYPE_USE})
@libcore.api.IntraCoreApi
-public @interface Nullable {
- /**
- * Min Android API level (inclusive) to which this annotation is applied.
- */
- int from() default Integer.MIN_VALUE;
-
- /**
- * Max Android API level to which this annotation is applied.
- */
- int to() default Integer.MAX_VALUE;
-}
+public @interface Nullable {}
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index 735635cc309a..b41ce0f65017 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -268,18 +268,45 @@ fun writeByteCodeToReturn(methodDescriptor: String, writer: MethodVisitor) {
}
/**
+ * Write bytecode to pop the 2 uninitialized instances out of the stack
+ * after performing constructor redirection.
+ */
+fun adjustStackForConstructorRedirection(writer: MethodVisitor) {
+ // Stack: { uninitialized, uninitialized, obj }
+ writer.visitInsn(Opcodes.SWAP)
+ // Stack: { uninitialized, obj, uninitialized }
+ writer.visitInsn(Opcodes.POP)
+ // Stack: { uninitialized, obj }
+ writer.visitInsn(Opcodes.SWAP)
+ // Stack: { obj, uninitialized }
+ writer.visitInsn(Opcodes.POP)
+ // Stack: { obj }
+
+ // We end up with only the desired object on the stack
+}
+
+/**
* Given a method descriptor, insert an [argType] as the first argument to it.
*/
fun prependArgTypeToMethodDescriptor(methodDescriptor: String, classInternalName: String): String {
val returnType = Type.getReturnType(methodDescriptor)
val argTypes = Type.getArgumentTypes(methodDescriptor).toMutableList()
- argTypes.add(0, Type.getType("L" + classInternalName + ";"))
+ argTypes.add(0, Type.getType("L$classInternalName;"))
return Type.getMethodDescriptor(returnType, *argTypes.toTypedArray())
}
/**
+ * Given a method descriptor, change the return type to [classInternalName].
+ */
+fun changeMethodDescriptorReturnType(methodDescriptor: String, classInternalName: String): String {
+ val argTypes = Type.getArgumentTypes(methodDescriptor)
+ val returnType = Type.getType("L$classInternalName;")
+ return Type.getMethodDescriptor(returnType, *argTypes)
+}
+
+/**
* Return the "visibility" modifier from an `access` integer.
*
* (see https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1)
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt
index c5a2f9ff5e96..bba4681d3838 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt
@@ -15,6 +15,7 @@
*/
package com.android.hoststubgen.filters
+import com.android.hoststubgen.log
import org.objectweb.asm.commons.Remapper
/**
@@ -23,19 +24,25 @@ import org.objectweb.asm.commons.Remapper
class FilterRemapper(val filter: OutputFilter) : Remapper() {
private val cache = mutableMapOf<String, String>()
- override fun mapType(typeInternalName: String?): String? {
+
+ override fun map(typeInternalName: String?): String? {
if (typeInternalName == null) {
return null
}
cache[typeInternalName]?.let {
+ // log.d("Cached rename from $typeInternalName to $it")
return it
}
- var mapped = filter.remapType(typeInternalName) ?: typeInternalName
+ var mapped = filter.remapType(typeInternalName)
+ if (mapped != null) {
+ log.d("Renaming type $typeInternalName to $mapped")
+ } else {
+ // log.d("Not renaming type $typeInternalName")
+ }
+ mapped = mapped ?: typeInternalName
cache[typeInternalName] = mapped
return mapped
}
-
- // TODO Do we need to implement mapPackage(), etc too?
} \ No newline at end of file
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index d0c97c006647..dd353e9caeff 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -100,7 +100,6 @@ interface PolicyFileProcessor {
methodName: String,
methodDesc: String,
replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
- policy: FilterPolicyWithReason,
)
}
@@ -286,9 +285,10 @@ class TextFileFilterPolicyBuilder(
methodName: String,
methodDesc: String,
replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
- policy: FilterPolicyWithReason,
) {
- imf.setPolicyForMethod(className, methodName, methodDesc, policy)
+ // Keep the source method, because the target method may call it.
+ imf.setPolicyForMethod(className, methodName, methodDesc,
+ FilterPolicy.Keep.withReason(FILTER_REASON))
methodReplaceSpec.add(replaceSpec)
}
}
@@ -642,7 +642,6 @@ class TextFileFilterPolicyParser {
methodName,
signature,
spec,
- policyWithReason,
)
} else {
// It's an in-class replace.
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapperFilter.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapperFilter.kt
index a78c6552b8d0..bc90d1248322 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapperFilter.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapperFilter.kt
@@ -15,7 +15,6 @@
*/
package com.android.hoststubgen.filters
-import com.android.hoststubgen.log
import java.util.regex.Pattern
/**
@@ -34,17 +33,12 @@ class TextFilePolicyRemapperFilter(
val typeInternalNamePrefix: String,
)
- private val cache = mutableMapOf<String, String>()
-
override fun remapType(className: String): String? {
- var mapped: String = className
typeRenameSpecs.forEach {
if (it.typeInternalNamePattern.matcher(className).matches()) {
- mapped = it.typeInternalNamePrefix + className
- log.d("Renaming type $className to $mapped")
+ return it.typeInternalNamePrefix + className
}
}
- cache[className] = mapped
- return mapped
+ return null
}
}
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
index 70e7d46bb6cd..b8a357668c2b 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -17,7 +17,10 @@ package com.android.hoststubgen.visitors
import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
+import com.android.hoststubgen.asm.CTOR_NAME
import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.adjustStackForConstructorRedirection
+import com.android.hoststubgen.asm.changeMethodDescriptorReturnType
import com.android.hoststubgen.asm.prependArgTypeToMethodDescriptor
import com.android.hoststubgen.asm.writeByteCodeToPushArguments
import com.android.hoststubgen.asm.writeByteCodeToReturn
@@ -33,6 +36,7 @@ import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Opcodes.INVOKEINTERFACE
+import org.objectweb.asm.Opcodes.INVOKESPECIAL
import org.objectweb.asm.Opcodes.INVOKESTATIC
import org.objectweb.asm.Opcodes.INVOKEVIRTUAL
import org.objectweb.asm.Type
@@ -376,53 +380,90 @@ class ImplGeneratingAdapter(
val callerMethodName: String,
next: MethodVisitor?,
) : MethodVisitor(OPCODE_VERSION, next) {
- override fun visitMethodInsn(
+
+ private fun doReplace(
opcode: Int,
- owner: String?,
- name: String?,
- descriptor: String?,
- isInterface: Boolean,
- ) {
+ owner: String,
+ name: String,
+ descriptor: String,
+ ): Boolean {
when (opcode) {
INVOKESTATIC, INVOKEVIRTUAL, INVOKEINTERFACE -> {}
- else -> {
- // Don't touch other opcodes.
- super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
- return
- }
+ // We only support INVOKESPECIAL when replacing constructors.
+ INVOKESPECIAL -> if (name != CTOR_NAME) return false
+ // Don't touch other opcodes.
+ else -> return false
}
+
val to = filter.getMethodCallReplaceTo(
- currentClassName, callerMethodName, owner!!, name!!, descriptor!!
+ currentClassName, callerMethodName, owner, name, descriptor
)
if (to == null
// Don't replace if the target is the callsite.
|| (to.className == currentClassName && to.methodName == callerMethodName)
) {
- super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
- return
+ return false
}
- // Replace the method call with a (static) call to the target method.
- // If it's a non-static call, the target method's first argument will receive "this".
- // (Because of that, we don't need to manipulate the stack. Just replace the
- // method call.)
+ if (opcode != INVOKESPECIAL) {
+ // It's either a static method call or virtual method call.
+ // Either way, we don't manipulate the stack and send the original arguments
+ // as is to the target method.
+ //
+ // If the call is a virtual call (INVOKEVIRTUAL or INVOKEINTERFACE), then
+ // the first argument in the stack is the "this" object, so the target
+ // method must have an extra argument as the first argument to receive it.
+ // We update the method descriptor with prependArgTypeToMethodDescriptor()
+ // to absorb this difference.
+
+ val toDesc = if (opcode == INVOKESTATIC) {
+ descriptor
+ } else {
+ prependArgTypeToMethodDescriptor(descriptor, owner)
+ }
- val toDesc = if (opcode == INVOKESTATIC) {
- // Static call to static call, no need to change the desc.
- descriptor
+ mv.visitMethodInsn(
+ INVOKESTATIC,
+ to.className,
+ to.methodName,
+ toDesc,
+ false
+ )
} else {
- // Need to prepend the "this" type to the descriptor.
- prependArgTypeToMethodDescriptor(descriptor, owner)
+ // Because an object initializer does not return a value, the newly created
+ // but uninitialized object will be dup-ed at the bottom of the stack.
+ // We first call the target method to consume the constructor arguments at the top.
+
+ val toDesc = changeMethodDescriptorReturnType(descriptor, owner)
+
+ // Before stack: { uninitialized, uninitialized, args... }
+ mv.visitMethodInsn(
+ INVOKESTATIC,
+ to.className,
+ to.methodName,
+ toDesc,
+ false
+ )
+ // After stack: { uninitialized, uninitialized, obj }
+
+ // Next we pop the 2 uninitialized instances out of the stack.
+ adjustStackForConstructorRedirection(mv)
}
- mv.visitMethodInsn(
- INVOKESTATIC,
- to.className,
- to.methodName,
- toDesc,
- false
- )
+ return true
+ }
+
+ override fun visitMethodInsn(
+ opcode: Int,
+ owner: String,
+ name: String,
+ descriptor: String,
+ isInterface: Boolean,
+ ) {
+ if (!doReplace(opcode, owner, name, descriptor)) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
+ }
}
}
}
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 635f66d8e90c..2b942a91a8f8 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -1883,6 +1883,42 @@ BootstrapMethods:
InnerClasses:
public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+ Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+ minor version: 0
+ major version: 65
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 3
+Constant pool:
+{
+ public int i;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: aload_0
+ x: iload_1
+ x: putfield #x // Field i:I
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ 0 10 1 i I
+}
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
Compiled from "TinyFrameworkMethodCallReplace.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -1891,7 +1927,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 3
+ interfaces: 0, fields: 0, methods: 4, attributes: 3
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -1937,10 +1973,28 @@ Constant pool:
Start Length Slot Name Signature
0 4 0 a I
0 4 1 b I
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: iconst_1
+ x: iadd
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 i I
}
SourceFile: "TinyFrameworkMethodCallReplace.java"
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -1950,7 +2004,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 5, attributes: 5
+ interfaces: 0, fields: 0, methods: 6, attributes: 5
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2008,6 +2062,21 @@ Constant pool:
x: ireturn
LineNumberTable:
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 i I
+
private static int originalAdd(int, int);
descriptor: (II)I
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
@@ -2046,6 +2115,7 @@ RuntimeInvisibleAnnotations:
android.hosttest.annotation.HostSideTestWholeClassKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
BootstrapMethods:
x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
@@ -2053,8 +2123,9 @@ BootstrapMethods:
#x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V
#x ()V
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+ public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
Compiled from "TinyFrameworkNative.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
@@ -3198,7 +3269,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 2
+ interfaces: 0, fields: 0, methods: 3, attributes: 2
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
@@ -3229,6 +3300,22 @@ Constant pool:
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 value I
+
+ public static int bar(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ x: iload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getArray:(I)[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: iconst_0
+ x: aaload
+ x: invokevirtual #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 value I
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeInvisibleAnnotations:
@@ -3242,7 +3329,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 2
+ interfaces: 0, fields: 1, methods: 3, attributes: 2
Constant pool:
{
private final int mValue;
@@ -3278,6 +3365,26 @@ Constant pool:
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed[] getArray(int);
+ descriptor: (I)[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=6, locals=1, args_size=1
+ x: iconst_1
+ x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iconst_0
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method "<init>":(I)V
+ x: aastore
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 16 0 value I
}
SourceFile: "TinyFrameworkToBeRenamed.java"
RuntimeInvisibleAnnotations:
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt
index 51a33554afa9..d493ad152225 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt
@@ -2002,6 +2002,51 @@ BootstrapMethods:
#x ()Ljava/lang/Integer;
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+ Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+ minor version: 0
+ major version: 65
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+Constant pool:
+{
+ public int i;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: aload_0
+ x: iload_1
+ x: putfield #x // Field i:I
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ 0 10 1 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
Compiled from "TinyFrameworkMethodCallReplace.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2010,7 +2055,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 4
+ interfaces: 0, fields: 0, methods: 4, attributes: 4
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -2065,9 +2110,30 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: iconst_1
+ x: iadd
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
x: #x()
@@ -2081,7 +2147,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 6
+ interfaces: 0, fields: 0, methods: 6, attributes: 6
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2148,6 +2214,48 @@ Constant pool:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: swap
+ x: pop
+ x: swap
+ x: pop
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 13 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ private static int originalAdd(int, int);
+ descriptor: (II)I
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=2, args_size=2
+ x: iload_0
+ x: iload_1
+ x: iadd
+ x: iconst_1
+ x: isub
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 a I
+ 0 6 1 b I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
@@ -2167,6 +2275,7 @@ Constant pool:
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2184,6 +2293,7 @@ BootstrapMethods:
#x ()V
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
Compiled from "TinyFrameworkNative.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
@@ -3392,7 +3502,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
@@ -3429,6 +3539,25 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static int bar(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ x: iload_0
+ x: invokestatic #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getArray:(I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: iconst_0
+ x: aaload
+ x: invokevirtual #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeVisibleAnnotations:
@@ -3867,7 +3996,7 @@ public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFramew
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 3
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
Constant pool:
{
private final int mValue;
@@ -3891,7 +4020,7 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 0 10 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
0 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
@@ -3908,7 +4037,30 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 0 5 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed[] getArray(int);
+ descriptor: (I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=6, locals=1, args_size=1
+ x: iconst_1
+ x: anewarray #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iconst_0
+ x: new #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method "<init>":(I)V
+ x: aastore
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 16 0 value I
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
index a466a2e2c3a7..8978a7acefd8 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
@@ -2413,6 +2413,66 @@ BootstrapMethods:
#x ()Ljava/lang/Integer;
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+ Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+ minor version: 0
+ major version: 65
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 4
+Constant pool:
+{
+ public int i;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: ldc #x // String <init>
+ x: ldc #x // String (I)V
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: aload_0
+ x: iload_1
+ x: putfield #x // Field i:I
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ 11 10 1 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
Compiled from "TinyFrameworkMethodCallReplace.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2421,7 +2481,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 4
+ interfaces: 0, fields: 0, methods: 5, attributes: 4
Constant pool:
{
private static {};
@@ -2501,8 +2561,34 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ x: ldc #x // String newConstructorTester
+ x: ldc #x // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: iconst_1
+ x: iadd
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
@@ -2517,7 +2603,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 5, attributes: 6
+ interfaces: 0, fields: 0, methods: 7, attributes: 6
Constant pool:
{
private static {};
@@ -2609,18 +2695,70 @@ Constant pool:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ x: ldc #x // String constructorReplaceTester
+ x: ldc #x // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: swap
+ x: pop
+ x: swap
+ x: pop
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 13 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ private static int originalAdd(int, int);
+ descriptor: (II)I
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=4, locals=2, args_size=2
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ x: ldc #x // String originalAdd
+ x: ldc #x // String (II)I
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: iload_0
+ x: iload_1
+ x: iadd
+ x: iconst_1
+ x: isub
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 6 0 a I
+ 11 6 1 b I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=4, locals=1, args_size=1
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- x: ldc #x // String lambda$nonStaticMethodCallReplaceTester$0
- x: ldc #x // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
+ x: ldc #x // String lambda$nonStaticMethodCallReplaceTester$0
+ x: ldc #x // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
x: aload_0
- x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
+ x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z
x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V
x: return
@@ -2633,6 +2771,7 @@ Constant pool:
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2650,6 +2789,7 @@ BootstrapMethods:
#x ()V
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
Compiled from "TinyFrameworkNative.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
@@ -4241,7 +4381,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 3
+ interfaces: 0, fields: 0, methods: 4, attributes: 3
Constant pool:
{
private static {};
@@ -4298,6 +4438,30 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static int bar(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
+ x: ldc #x // String bar
+ x: ldc #x // String (I)I
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: iload_0
+ x: invokestatic #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getArray:(I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: iconst_0
+ x: aaload
+ x: invokevirtual #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 10 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeVisibleAnnotations:
@@ -4947,7 +5111,7 @@ public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFramew
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 3, attributes: 3
+ interfaces: 0, fields: 1, methods: 4, attributes: 3
Constant pool:
{
private final int mValue;
@@ -4962,8 +5126,8 @@ Constant pool:
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4972,7 +5136,7 @@ Constant pool:
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=2, args_size=2
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
x: ldc #x // String <init>
x: ldc #x // String (I)V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -4986,7 +5150,7 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 11 10 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
11 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
@@ -4997,7 +5161,7 @@ Constant pool:
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
x: ldc #x // String getValue
x: ldc #x // String ()I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -5008,7 +5172,35 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 11 5 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed[] getArray(int);
+ descriptor: (I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=6, locals=1, args_size=1
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // String getArray
+ x: ldc #x // String (I)[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: iconst_1
+ x: anewarray #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iconst_0
+ x: new #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method "<init>":(I)V
+ x: aastore
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 16 0 value I
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 78341d7afbb9..406c61138705 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -1883,6 +1883,42 @@ BootstrapMethods:
InnerClasses:
public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+ Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 3
+Constant pool:
+{
+ public int i;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: aload_0
+ x: iload_1
+ x: putfield #x // Field i:I
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ 0 10 1 i I
+}
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
Compiled from "TinyFrameworkMethodCallReplace.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -1891,7 +1927,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 3
+ interfaces: 0, fields: 0, methods: 4, attributes: 3
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -1937,10 +1973,28 @@ Constant pool:
Start Length Slot Name Signature
0 4 0 a I
0 4 1 b I
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: iconst_1
+ x: iadd
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 i I
}
SourceFile: "TinyFrameworkMethodCallReplace.java"
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -1950,7 +2004,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 5, attributes: 5
+ interfaces: 0, fields: 0, methods: 6, attributes: 5
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2008,6 +2062,21 @@ Constant pool:
x: ireturn
LineNumberTable:
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 i I
+
private static int originalAdd(int, int);
descriptor: (II)I
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
@@ -2046,6 +2115,7 @@ RuntimeInvisibleAnnotations:
android.hosttest.annotation.HostSideTestWholeClassKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
BootstrapMethods:
x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
@@ -2053,8 +2123,9 @@ BootstrapMethods:
#x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V
#x ()V
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+ public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
Compiled from "TinyFrameworkNative.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
@@ -3219,7 +3290,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 2
+ interfaces: 0, fields: 0, methods: 3, attributes: 2
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
@@ -3250,6 +3321,22 @@ Constant pool:
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 value I
+
+ public static int bar(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ x: iload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getArray:(I)[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: iconst_0
+ x: aaload
+ x: invokevirtual #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 value I
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeInvisibleAnnotations:
@@ -3263,7 +3350,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 2
+ interfaces: 0, fields: 1, methods: 3, attributes: 2
Constant pool:
{
private final int mValue;
@@ -3299,6 +3386,26 @@ Constant pool:
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed[] getArray(int);
+ descriptor: (I)[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=6, locals=1, args_size=1
+ x: iconst_1
+ x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iconst_0
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method "<init>":(I)V
+ x: aastore
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 16 0 value I
}
SourceFile: "TinyFrameworkToBeRenamed.java"
RuntimeInvisibleAnnotations:
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
index 2e0b1820a696..6a8e4885d1d0 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
@@ -2002,6 +2002,51 @@ BootstrapMethods:
#x ()Ljava/lang/Integer;
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+ Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+Constant pool:
+{
+ public int i;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: aload_0
+ x: iload_1
+ x: putfield #x // Field i:I
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ 0 10 1 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
Compiled from "TinyFrameworkMethodCallReplace.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2010,7 +2055,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 4
+ interfaces: 0, fields: 0, methods: 4, attributes: 4
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -2065,9 +2110,30 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: iconst_1
+ x: iadd
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
x: #x()
@@ -2081,7 +2147,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 6
+ interfaces: 0, fields: 0, methods: 6, attributes: 6
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2148,6 +2214,48 @@ Constant pool:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: swap
+ x: pop
+ x: swap
+ x: pop
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 13 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ private static int originalAdd(int, int);
+ descriptor: (II)I
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=2, args_size=2
+ x: iload_0
+ x: iload_1
+ x: iadd
+ x: iconst_1
+ x: isub
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 a I
+ 0 6 1 b I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
@@ -2167,6 +2275,7 @@ Constant pool:
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2184,6 +2293,7 @@ BootstrapMethods:
#x ()V
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
Compiled from "TinyFrameworkNative.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
@@ -3422,7 +3532,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
Constant pool:
{
public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
@@ -3459,6 +3569,25 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static int bar(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ x: iload_0
+ x: invokestatic #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getArray:(I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: iconst_0
+ x: aaload
+ x: invokevirtual #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeVisibleAnnotations:
@@ -3897,7 +4026,7 @@ public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFramew
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 3
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
Constant pool:
{
private final int mValue;
@@ -3921,7 +4050,7 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 0 10 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
0 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
@@ -3938,7 +4067,30 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 0 5 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed[] getArray(int);
+ descriptor: (I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=6, locals=1, args_size=1
+ x: iconst_1
+ x: anewarray #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iconst_0
+ x: new #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method "<init>":(I)V
+ x: aastore
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 16 0 value I
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
index 51f79258d53a..d8e76321b038 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
@@ -2413,6 +2413,66 @@ BootstrapMethods:
#x ()Ljava/lang/Integer;
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+ Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 4
+Constant pool:
+{
+ public int i;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: ldc #x // String <init>
+ x: ldc #x // String (I)V
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: aload_0
+ x: iload_1
+ x: putfield #x // Field i:I
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ 11 10 1 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
Compiled from "TinyFrameworkMethodCallReplace.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2421,7 +2481,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 4
+ interfaces: 0, fields: 0, methods: 5, attributes: 4
Constant pool:
{
private static {};
@@ -2501,8 +2561,34 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ x: ldc #x // String newConstructorTester
+ x: ldc #x // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: iconst_1
+ x: iadd
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
@@ -2517,7 +2603,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 5, attributes: 6
+ interfaces: 0, fields: 0, methods: 7, attributes: 6
Constant pool:
{
private static {};
@@ -2609,18 +2695,70 @@ Constant pool:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+ descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ x: ldc #x // String constructorReplaceTester
+ x: ldc #x // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+ x: dup
+ x: iload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+ x: swap
+ x: pop
+ x: swap
+ x: pop
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 13 0 i I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ private static int originalAdd(int, int);
+ descriptor: (II)I
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=4, locals=2, args_size=2
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ x: ldc #x // String originalAdd
+ x: ldc #x // String (II)I
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: iload_0
+ x: iload_1
+ x: iadd
+ x: iconst_1
+ x: isub
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 6 0 a I
+ 11 6 1 b I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=4, locals=1, args_size=1
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- x: ldc #x // String lambda$nonStaticMethodCallReplaceTester$0
- x: ldc #x // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
+ x: ldc #x // String lambda$nonStaticMethodCallReplaceTester$0
+ x: ldc #x // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
x: aload_0
- x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
+ x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z
x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V
x: return
@@ -2633,6 +2771,7 @@ Constant pool:
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
+ public static #x= #x of #x; // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2650,6 +2789,7 @@ BootstrapMethods:
#x ()V
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
Compiled from "TinyFrameworkNative.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
@@ -4271,7 +4411,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 3
+ interfaces: 0, fields: 0, methods: 4, attributes: 3
Constant pool:
{
private static {};
@@ -4328,6 +4468,30 @@ Constant pool:
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static int bar(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
+ x: ldc #x // String bar
+ x: ldc #x // String (I)I
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: iload_0
+ x: invokestatic #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getArray:(I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: iconst_0
+ x: aaload
+ x: invokevirtual #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I
+ x: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 10 0 value I
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeVisibleAnnotations:
@@ -4977,7 +5141,7 @@ public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFramew
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 3, attributes: 3
+ interfaces: 0, fields: 1, methods: 4, attributes: 3
Constant pool:
{
private final int mValue;
@@ -4992,8 +5156,8 @@ Constant pool:
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -5002,7 +5166,7 @@ Constant pool:
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=2, args_size=2
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
x: ldc #x // String <init>
x: ldc #x // String (I)V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -5016,7 +5180,7 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 11 10 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
11 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
@@ -5027,7 +5191,7 @@ Constant pool:
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
x: ldc #x // String getValue
x: ldc #x // String ()I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -5038,7 +5202,35 @@ Constant pool:
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ 11 5 0 this Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed[] getArray(int);
+ descriptor: (I)[Lrename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=6, locals=1, args_size=1
+ x: ldc #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // String getArray
+ x: ldc #x // String (I)[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: iconst_1
+ x: anewarray #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iconst_0
+ x: new #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: dup
+ x: iload_0
+ x: invokespecial #x // Method "<init>":(I)V
+ x: aastore
+ x: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 16 0 value I
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
index 1f64a3c78c53..cbaad2e85717 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -68,6 +68,10 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace
class java.lang.Thread keep
method start ()V @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.startThread
+# Used to test constructor replacement.
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester keepclass
+ method <init> (I)V @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester
+
# "rename" takes a type internal name, so '/'s is used as a separator.
# The leading / in the prefix is not needed (it'll be stripped), but it's added to make
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
index 57c69a336654..d850be82719f 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
@@ -41,10 +41,23 @@ public class TinyFrameworkMethodCallReplace {
return originalAdd(1, 2);
}
+ public static ConstructorTester constructorReplaceTester(int i) {
+ // This object construction will be replaced with ReplaceTo.newConstructorTester().
+ return new ConstructorTester(i);
+ }
+
private static int originalAdd(int a, int b) {
return a + b - 1; // Original is broken.
}
+ public static class ConstructorTester {
+ public int i;
+
+ public ConstructorTester(int i) {
+ this.i = i;
+ }
+ }
+
public static class ReplaceTo {
public static void startThread(Thread thread) {
thread.setDaemon(true);
@@ -54,5 +67,9 @@ public class TinyFrameworkMethodCallReplace {
public static int add(int a, int b) {
return a + b;
}
+
+ public static ConstructorTester newConstructorTester(int i) {
+ return new ConstructorTester(i + 1);
+ }
}
}
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
index 707bc0ebb4db..74e4610187c4 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
@@ -25,4 +25,9 @@ public class TinyFrameworkRenamedClassCaller {
// so this code should work as-is.
return new TinyFrameworkToBeRenamed(value).getValue();
}
+
+ /** Calls the class that'll be renamed. */
+ public static int bar(int value) {
+ return TinyFrameworkToBeRenamed.getArray(value)[0].getValue();
+ }
}
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
index 8319ced6109a..7dcc83e79e26 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
@@ -31,4 +31,8 @@ public class TinyFrameworkToBeRenamed {
public int getValue() {
return mValue;
}
+
+ public static TinyFrameworkToBeRenamed[] getArray(int value) {
+ return new TinyFrameworkToBeRenamed[] { new TinyFrameworkToBeRenamed(value) };
+ }
}
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
index 68673dc2a5b8..89fcd30b3df5 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -308,6 +308,11 @@ public class TinyFrameworkClassTest {
}
@Test
+ public void testTypeRenameArray() {
+ assertThat(TinyFrameworkRenamedClassCaller.bar(2)).isEqualTo(2);
+ }
+
+ @Test
public void testMethodCallReplaceNonStatic() throws Exception {
assertThat(TinyFrameworkMethodCallReplace.nonStaticMethodCallReplaceTester())
.isEqualTo(true);
@@ -318,4 +323,10 @@ public class TinyFrameworkClassTest {
assertThat(TinyFrameworkMethodCallReplace.staticMethodCallReplaceTester())
.isEqualTo(3);
}
+
+ @Test
+ public void testConstructorCallReplace() throws Exception {
+ assertThat(TinyFrameworkMethodCallReplace.constructorReplaceTester(5).i)
+ .isEqualTo(6);
+ }
}
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
index b6089eaff1ed..a7f481a02533 100644
--- a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
@@ -449,7 +449,6 @@ private class TextPolicyToAnnotationConverter(
methodName: String,
methodDesc: String,
replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
- policy: FilterPolicyWithReason
) {
// This can't be converted to an annotation.
classHasMember = true
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
index bb3c710b0c23..0f6f86b39458 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
@@ -103,12 +103,16 @@ public class AutoclickController extends BaseEventStreamTransformation {
@Override
public void toggleAutoclickPause(boolean paused) {
if (paused) {
- if (mClickScheduler != null) {
- mClickScheduler.cancel();
- }
- if (mAutoclickIndicatorScheduler != null) {
- mAutoclickIndicatorScheduler.cancel();
- }
+ cancelPendingClick();
+ }
+ }
+
+ @Override
+ public void onHoverChange(boolean hovered) {
+ // Cancel all pending clicks when the mouse moves outside the panel while
+ // autoclick is still paused.
+ if (!hovered && isPaused()) {
+ cancelPendingClick();
}
}
};
@@ -226,8 +230,17 @@ public class AutoclickController extends BaseEventStreamTransformation {
}
private boolean isPaused() {
- // TODO (b/397460424): Unpause when hovering over panel.
- return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isPaused();
+ return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isPaused()
+ && !mAutoclickTypePanel.isHovered();
+ }
+
+ private void cancelPendingClick() {
+ if (mClickScheduler != null) {
+ mClickScheduler.cancel();
+ }
+ if (mAutoclickIndicatorScheduler != null) {
+ mAutoclickIndicatorScheduler.cancel();
+ }
}
@VisibleForTesting
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickLinearLayout.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickLinearLayout.java
new file mode 100644
index 000000000000..fe8adf75704d
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickLinearLayout.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.autoclick;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.LinearLayout;
+
+/**
+ * A custom LinearLayout that provides enhanced hover event handling.
+ * This class overrides hover methods to track hover events for the entire panel ViewGroup,
+ * including the descendant buttons. This allows for consistent hover behavior and feedback
+ * across the entire layout.
+ */
+public class AutoclickLinearLayout extends LinearLayout {
+ public interface OnHoverChangedListener {
+ /**
+ * Called when the hover state of the AutoclickLinearLayout changes.
+ *
+ * @param hovered {@code true} if the view is now hovered, {@code false} otherwise.
+ */
+ void onHoverChanged(boolean hovered);
+ }
+
+ private OnHoverChangedListener mListener;
+
+ public AutoclickLinearLayout(Context context) {
+ super(context);
+ }
+
+ public AutoclickLinearLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AutoclickLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public AutoclickLinearLayout(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public void setOnHoverChangedListener(OnHoverChangedListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public boolean onInterceptHoverEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+ setHovered(action == MotionEvent.ACTION_HOVER_ENTER
+ || action == MotionEvent.ACTION_HOVER_MOVE);
+
+ return false;
+ }
+
+ @Override
+ public void onHoverChanged(boolean hovered) {
+ super.onHoverChanged(hovered);
+
+ if (mListener != null) {
+ mListener.onHoverChanged(hovered);
+ }
+ }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
index ab4b3b13eece..57bbb4a7a0a7 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
@@ -110,11 +110,18 @@ public class AutoclickTypePanel {
* @param paused {@code true} to pause autoclick, {@code false} to resume.
*/
void toggleAutoclickPause(boolean paused);
+
+ /**
+ * Called when the hovered state of the panel changes.
+ *
+ * @param hovered {@code true} if the panel is now hovered, {@code false} otherwise.
+ */
+ void onHoverChange(boolean hovered);
}
private final Context mContext;
- private final View mContentView;
+ private final AutoclickLinearLayout mContentView;
private final WindowManager mWindowManager;
@@ -164,8 +171,9 @@ public class AutoclickTypePanel {
R.drawable.accessibility_autoclick_resume);
mContentView =
- LayoutInflater.from(context)
+ (AutoclickLinearLayout) LayoutInflater.from(context)
.inflate(R.layout.accessibility_autoclick_type_panel, null);
+ mContentView.setOnHoverChangedListener(mClickPanelController::onHoverChange);
mLeftClickButton =
mContentView.findViewById(R.id.accessibility_autoclick_left_click_layout);
mRightClickButton =
@@ -339,6 +347,10 @@ public class AutoclickTypePanel {
return mPaused;
}
+ public boolean isHovered() {
+ return mContentView.isHovered();
+ }
+
/** Toggles the panel expanded or collapsed state. */
private void togglePanelExpansion(@AutoclickType int clickType) {
final LinearLayout button = getButtonFromClickType(clickType);
@@ -520,7 +532,7 @@ public class AutoclickTypePanel {
@VisibleForTesting
@NonNull
- View getContentViewForTesting() {
+ AutoclickLinearLayout getContentViewForTesting() {
return mContentView;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4187ee274f56..5395d2a914ec 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2625,6 +2625,13 @@ public final class ActiveServices {
}
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
r.foregroundNoti = notification;
+ if (r.isForeground && foregroundServiceType != previousFgsType) {
+ // An already foreground service is being started with a different fgs type
+ // which results in the type changing without typical startForeground
+ // logging.
+ Slog.w(TAG_SERVICE, "FGS type change for " + r.shortInstanceName
+ + " from " + previousFgsType + " to " + foregroundServiceType);
+ }
mAm.mProcessStateController.setForegroundServiceType(r, foregroundServiceType);
if (!r.isForeground) {
final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -9191,7 +9198,9 @@ public final class ActiveServices {
} else {
synchronized (mAm.mPidsSelfLocked) {
callerApp = mAm.mPidsSelfLocked.get(callingPid);
- caller = callerApp.getThread();
+ if (callerApp != null) {
+ caller = callerApp.getThread();
+ }
}
}
if (callerApp == null) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c8b8909f203f..f7d7ed541780 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3006,7 +3006,7 @@ public class AppOpsService extends IAppOpsService.Stub {
UidState uidState = getUidStateLocked(uid, false);
if (uidState != null) {
int rawUidMode = mAppOpsCheckingService.getUidMode(
- uidState.uid, getPersistentId(virtualDeviceId), code);
+ uidState.uid, getPersistentDeviceIdForOp(virtualDeviceId, code), code);
if (rawUidMode != AppOpsManager.opToDefaultMode(code)) {
return raw ? rawUidMode :
@@ -3069,7 +3069,7 @@ public class AppOpsService extends IAppOpsService.Stub {
int switchCode = AppOpsManager.opToSwitch(code);
int rawUidMode = mAppOpsCheckingService.getUidMode(uid,
- getPersistentId(virtualDeviceId), switchCode);
+ getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode);
if (rawUidMode != AppOpsManager.opToDefaultMode(switchCode)) {
return raw ? rawUidMode : evaluateForegroundMode(uid, switchCode, rawUidMode);
@@ -3396,7 +3396,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
final Op op = getOpLocked(ops, code, uid, true);
final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag,
- getPersistentId(virtualDeviceId));
+ getPersistentDeviceIdForOp(virtualDeviceId, code));
if (attributedOp.isRunning()) {
Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code "
+ code + " startTime of in progress event="
@@ -3418,15 +3418,15 @@ public class AppOpsService extends IAppOpsService.Stub {
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
- } else if (mAppOpsCheckingService.getUidMode(
- uidState.uid, getPersistentId(virtualDeviceId), switchCode)
+ } else if (mAppOpsCheckingService.getUidMode(uidState.uid,
+ getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode)
!= AppOpsManager.opToDefaultMode(switchCode)) {
final int uidMode =
uidState.evalMode(
code,
mAppOpsCheckingService.getUidMode(
uidState.uid,
- getPersistentId(virtualDeviceId),
+ getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
switchCode));
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
@@ -3478,7 +3478,8 @@ public class AppOpsService extends IAppOpsService.Stub {
virtualDeviceId, flags, AppOpsManager.MODE_ALLOWED);
attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag,
- getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags, notedCount);
+ getPersistentDeviceIdForOp(proxyVirtualDeviceId, code), uidState.getState(),
+ flags, notedCount);
if (shouldCollectAsyncNotedOp) {
collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message,
@@ -4045,7 +4046,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
final Op op = getOpLocked(ops, code, uid, true);
final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag,
- getPersistentId(virtualDeviceId));
+ getPersistentDeviceIdForOp(virtualDeviceId, code));
final UidState uidState = ops.uidState;
isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag,
virtualDeviceId, pvr.bypass, false);
@@ -4058,8 +4059,9 @@ public class AppOpsService extends IAppOpsService.Stub {
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
} else if ((rawUidMode =
- mAppOpsCheckingService.getUidMode(
- uidState.uid, getPersistentId(virtualDeviceId), switchCode))
+ mAppOpsCheckingService.getUidMode(
+ uidState.uid, getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
+ switchCode))
!= AppOpsManager.opToDefaultMode(switchCode)) {
final int uidMode = uidState.evalMode(code, rawUidMode);
if (!shouldStartForMode(uidMode, startIfModeDefault)) {
@@ -4107,11 +4109,13 @@ public class AppOpsService extends IAppOpsService.Stub {
try {
if (isRestricted) {
attributedOp.createPaused(clientId, virtualDeviceId, proxyUid, proxyPackageName,
- proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
+ proxyAttributionTag,
+ getPersistentDeviceIdForOp(proxyVirtualDeviceId, code),
uidState.getState(), flags, attributionFlags, attributionChainId);
} else {
attributedOp.started(clientId, virtualDeviceId, proxyUid, proxyPackageName,
- proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
+ proxyAttributionTag,
+ getPersistentDeviceIdForOp(proxyVirtualDeviceId, code),
uidState.getState(), flags, attributionFlags, attributionChainId);
startType = START_TYPE_STARTED;
}
@@ -4179,15 +4183,15 @@ public class AppOpsService extends IAppOpsService.Stub {
final int switchCode = AppOpsManager.opToSwitch(code);
// If there is a non-default mode per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
- if (mAppOpsCheckingService.getUidMode(
- uidState.uid, getPersistentId(virtualDeviceId), switchCode)
+ if (mAppOpsCheckingService.getUidMode(uidState.uid,
+ getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode)
!= AppOpsManager.opToDefaultMode(switchCode)) {
final int uidMode =
uidState.evalMode(
code,
mAppOpsCheckingService.getUidMode(
uidState.uid,
- getPersistentId(virtualDeviceId),
+ getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
switchCode));
if (!shouldStartForMode(uidMode, startIfModeDefault)) {
if (DEBUG) {
@@ -4350,7 +4354,8 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
final AttributedOp attributedOp =
- op.mDeviceAttributedOps.getOrDefault(getPersistentId(virtualDeviceId),
+ op.mDeviceAttributedOps.getOrDefault(
+ getPersistentDeviceIdForOp(virtualDeviceId, code),
new ArrayMap<>()).get(attributionTag);
if (attributedOp == null) {
Slog.e(TAG, "Attribution not found: uid=" + uid + " pkg=" + packageName + "("
@@ -4641,7 +4646,8 @@ public class AppOpsService extends IAppOpsService.Stub {
return true;
}
if (mVirtualDeviceManagerInternal == null) {
- return true;
+ Slog.w(TAG, "VirtualDeviceManagerInternal is null when device Id is non-default");
+ return false;
}
if (mVirtualDeviceManagerInternal.isValidVirtualDeviceId(virtualDeviceId)) {
mKnownDeviceIds.put(virtualDeviceId,
@@ -7310,7 +7316,13 @@ public class AppOpsService extends IAppOpsService.Stub {
return packageNames;
}
- @NonNull private String getPersistentId(int virtualDeviceId) {
+ // For ops associated with device aware permissions, if virtual device id is non-default, we
+ // will return string version of that id provided the virtual device has corresponding camera or
+ // audio policy.
+ @NonNull private String getPersistentDeviceIdForOp(int virtualDeviceId, int op) {
+ virtualDeviceId = PermissionManager.resolveDeviceIdForPermissionCheck(mContext,
+ virtualDeviceId, AppOpsManager.opToPermission(op));
+
if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
return PERSISTENT_DEVICE_ID_DEFAULT;
}
@@ -7319,6 +7331,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
String persistentId =
mVirtualDeviceManagerInternal.getPersistentIdForDevice(virtualDeviceId);
+
if (persistentId == null) {
persistentId = mKnownDeviceIds.get(virtualDeviceId);
}
diff --git a/services/core/java/com/android/server/appop/DiscreteOpsRegistry.java b/services/core/java/com/android/server/appop/DiscreteOpsRegistry.java
index 84402c85471f..12c35ae92cbe 100644
--- a/services/core/java/com/android/server/appop/DiscreteOpsRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteOpsRegistry.java
@@ -177,6 +177,8 @@ abstract class DiscreteOpsRegistry {
*/
abstract void writeAndClearOldAccessHistory();
+ void shutdown() {}
+
/** Remove all discrete op events. */
abstract void clearHistory();
diff --git a/services/core/java/com/android/server/appop/DiscreteOpsSqlRegistry.java b/services/core/java/com/android/server/appop/DiscreteOpsSqlRegistry.java
index 604cb30294a9..dc11be9aadb6 100644
--- a/services/core/java/com/android/server/appop/DiscreteOpsSqlRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteOpsSqlRegistry.java
@@ -57,13 +57,18 @@ import java.util.Set;
public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
private static final String TAG = "DiscreteOpsSqlRegistry";
+ private static final long DB_WRITE_INTERVAL = Duration.ofMinutes(10).toMillis();
+ private static final long EXPIRED_ENTRY_DELETION_INTERVAL = Duration.ofHours(6).toMillis();
+
+ // Event type handled by SqliteWriteHandler
+ private static final int WRITE_DATABASE_RECURRING = 1;
+ private static final int DELETE_EXPIRED_ENTRIES = 2;
+ private static final int WRITE_DATABASE_CACHE_FULL = 3;
+
private final Context mContext;
private final DiscreteOpsDbHelper mDiscreteOpsDbHelper;
private final SqliteWriteHandler mSqliteWriteHandler;
private final DiscreteOpCache mDiscreteOpCache = new DiscreteOpCache(512);
- private static final long THREE_HOURS = Duration.ofHours(3).toMillis();
- private static final int WRITE_CACHE_EVICTED_OP_EVENTS = 1;
- private static final int DELETE_OLD_OP_EVENTS = 2;
// Attribution chain id is used to identify an attribution source chain, This is
// set for startOp only. PermissionManagerService resets this ID on device restart, so
// we use previously persisted chain id as offset, and add it to chain id received from
@@ -83,6 +88,9 @@ public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
mSqliteWriteHandler = new SqliteWriteHandler(thread.getLooper());
mDiscreteOpsDbHelper = new DiscreteOpsDbHelper(context, databaseFile);
mChainIdOffset = mDiscreteOpsDbHelper.getLargestAttributionChainId();
+ mSqliteWriteHandler.sendEmptyMessageDelayed(WRITE_DATABASE_RECURRING, DB_WRITE_INTERVAL);
+ mSqliteWriteHandler.sendEmptyMessageDelayed(DELETE_EXPIRED_ENTRIES,
+ EXPIRED_ENTRY_DELETION_INTERVAL);
}
@Override
@@ -117,15 +125,14 @@ public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
}
@Override
- void writeAndClearOldAccessHistory() {
- // Let the sql impl also follow the same disk write frequencies as xml,
- // controlled by AppOpsService.
+ void shutdown() {
+ mSqliteWriteHandler.removeAllPendingMessages();
mDiscreteOpsDbHelper.insertDiscreteOps(mDiscreteOpCache.getAllEventsAndClear());
- if (!mSqliteWriteHandler.hasMessages(DELETE_OLD_OP_EVENTS)) {
- if (mSqliteWriteHandler.sendEmptyMessageDelayed(DELETE_OLD_OP_EVENTS, THREE_HOURS)) {
- Slog.w(TAG, "DELETE_OLD_OP_EVENTS is not queued");
- }
- }
+ }
+
+ @Override
+ void writeAndClearOldAccessHistory() {
+ // no-op
}
@Override
@@ -175,7 +182,7 @@ public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
@Nullable String attributionTagFilter, int opFlagsFilter,
Set<String> attributionExemptPkgs) {
// flush the cache into database before read.
- writeAndClearOldAccessHistory();
+ mDiscreteOpsDbHelper.insertDiscreteOps(mDiscreteOpCache.getAllEventsAndClear());
boolean assembleChains = attributionExemptPkgs != null;
IntArray opCodes = getAppOpCodes(filter, opNamesFilter);
beginTimeMillis = Math.max(beginTimeMillis, Instant.now().minus(sDiscreteHistoryCutoff,
@@ -363,20 +370,59 @@ public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case WRITE_CACHE_EVICTED_OP_EVENTS:
- List<DiscreteOp> opEvents = (List<DiscreteOp>) msg.obj;
- mDiscreteOpsDbHelper.insertDiscreteOps(opEvents);
- break;
- case DELETE_OLD_OP_EVENTS:
+ case WRITE_DATABASE_RECURRING -> {
+ try {
+ List<DiscreteOp> evictedEvents;
+ synchronized (mDiscreteOpCache) {
+ evictedEvents = mDiscreteOpCache.evict();
+ }
+ mDiscreteOpsDbHelper.insertDiscreteOps(evictedEvents);
+ } finally {
+ mSqliteWriteHandler.sendEmptyMessageDelayed(WRITE_DATABASE_RECURRING,
+ DB_WRITE_INTERVAL);
+ // Schedule a cleanup to truncate older (before cutoff time) entries.
+ if (!mSqliteWriteHandler.hasMessages(DELETE_EXPIRED_ENTRIES)) {
+ mSqliteWriteHandler.sendEmptyMessageDelayed(DELETE_EXPIRED_ENTRIES,
+ EXPIRED_ENTRY_DELETION_INTERVAL);
+ }
+ }
+ }
+ case DELETE_EXPIRED_ENTRIES -> {
long cutOffTimeStamp = System.currentTimeMillis() - sDiscreteHistoryCutoff;
mDiscreteOpsDbHelper.execSQL(
DiscreteOpsTable.DELETE_TABLE_DATA_BEFORE_ACCESS_TIME,
new Object[]{cutOffTimeStamp});
- break;
- default:
- throw new IllegalStateException("Unexpected value: " + msg.what);
+ }
+ case WRITE_DATABASE_CACHE_FULL -> {
+ try {
+ List<DiscreteOp> evictedEvents;
+ synchronized (mDiscreteOpCache) {
+ evictedEvents = mDiscreteOpCache.evict();
+ // if nothing to evict, just write the whole cache to database.
+ if (evictedEvents.isEmpty()
+ && mDiscreteOpCache.size() >= mDiscreteOpCache.capacity()) {
+ evictedEvents.addAll(mDiscreteOpCache.mCache);
+ mDiscreteOpCache.clear();
+ }
+ }
+ mDiscreteOpsDbHelper.insertDiscreteOps(evictedEvents);
+ } finally {
+ // Just in case initial message is not scheduled.
+ if (!mSqliteWriteHandler.hasMessages(WRITE_DATABASE_RECURRING)) {
+ mSqliteWriteHandler.sendEmptyMessageDelayed(WRITE_DATABASE_RECURRING,
+ DB_WRITE_INTERVAL);
+ }
+ }
+ }
+ default -> throw new IllegalStateException("Unexpected value: " + msg.what);
}
}
+
+ void removeAllPendingMessages() {
+ removeMessages(WRITE_DATABASE_RECURRING);
+ removeMessages(DELETE_EXPIRED_ENTRIES);
+ removeMessages(WRITE_DATABASE_CACHE_FULL);
+ }
}
/**
@@ -390,6 +436,7 @@ public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
* 4) During shutdown.
*/
class DiscreteOpCache {
+ private static final String TAG = "DiscreteOpCache";
private final int mCapacity;
private final ArraySet<DiscreteOp> mCache;
@@ -404,23 +451,9 @@ public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
return;
}
mCache.add(opEvent);
+
if (mCache.size() >= mCapacity) {
- if (DEBUG_LOG) {
- Slog.i(TAG, "Current discrete ops cache size: " + mCache.size());
- }
- List<DiscreteOp> evictedEvents = evict();
- if (DEBUG_LOG) {
- Slog.i(TAG, "Evicted discrete ops size: " + evictedEvents.size());
- }
- // if nothing to evict, just write the whole cache to disk
- if (evictedEvents.isEmpty()) {
- Slog.w(TAG, "No discrete ops event is evicted, write cache to db.");
- evictedEvents.addAll(mCache);
- mCache.clear();
- }
- Message msg = mSqliteWriteHandler.obtainMessage(
- WRITE_CACHE_EVICTED_OP_EVENTS, evictedEvents);
- mSqliteWriteHandler.sendMessage(msg);
+ mSqliteWriteHandler.sendEmptyMessage(WRITE_DATABASE_CACHE_FULL);
}
}
}
@@ -461,6 +494,14 @@ public class DiscreteOpsSqlRegistry extends DiscreteOpsRegistry {
}
}
+ int size() {
+ return mCache.size();
+ }
+
+ int capacity() {
+ return mCapacity;
+ }
+
/**
* Remove all entries from the cache.
*/
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 928a4b270b59..d267e0d9e536 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -750,6 +750,7 @@ final class HistoricalRegistry {
}
// Do not call persistPendingHistory inside the memory lock, due to possible deadlock
persistPendingHistory();
+ mDiscreteRegistry.shutdown();
}
void persistPendingHistory() {
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 964b97c7bbfd..551202c20cbb 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -1051,7 +1051,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
void handleHdrSdrNitsChanged(float displayNits, float sdrNits) {
final float newHdrSdrRatio;
- if (displayNits != INVALID_NITS && sdrNits != INVALID_NITS) {
+ if (displayNits != INVALID_NITS && sdrNits != INVALID_NITS
+ && (mBacklightAdapter.mUseSurfaceControlBrightness ||
+ mBacklightAdapter.mForceSurfaceControl)) {
// Ensure the ratio stays >= 1.0f as values below that are nonsensical
newHdrSdrRatio = Math.max(1.f, displayNits / sdrNits);
} else {
diff --git a/services/core/java/com/android/server/display/mode/ModeChangeObserver.java b/services/core/java/com/android/server/display/mode/ModeChangeObserver.java
index bbc13cc6ae7e..2751835f9958 100644
--- a/services/core/java/com/android/server/display/mode/ModeChangeObserver.java
+++ b/services/core/java/com/android/server/display/mode/ModeChangeObserver.java
@@ -23,8 +23,6 @@ import android.view.Display;
import android.view.DisplayAddress;
import android.view.DisplayEventReceiver;
-import com.android.internal.annotations.KeepForWeakReference;
-
import java.util.HashSet;
import java.util.Set;
@@ -35,7 +33,6 @@ final class ModeChangeObserver {
private final DisplayModeDirector.Injector mInjector;
@SuppressWarnings("unused")
- @KeepForWeakReference
private DisplayEventReceiver mModeChangeListener;
private final SparseArray<Set<Integer>> mRejectedModesByDisplay = new SparseArray<>();
private Looper mLooper;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 7e8bb28b6a37..144caea05d00 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -1365,6 +1365,21 @@ public final class DreamManagerService extends SystemService {
}
}
+ @Override
+ public void setScreensaverEnabled(boolean enabled) {
+ checkPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ final UserHandle userHandle = getCallingUserHandle();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ENABLED, enabled ? 1 : 0,
+ userHandle.getIdentifier());
+ mPowerManagerInternal.updateSettings();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
boolean canLaunchDreamActivity(String dreamPackageName, String packageName,
int callingUid) {
if (dreamPackageName == null || packageName == null) {
diff --git a/services/core/java/com/android/server/input/InputDataStore.java b/services/core/java/com/android/server/input/InputDataStore.java
index 834f8154240e..6ed50b6fbdcb 100644
--- a/services/core/java/com/android/server/input/InputDataStore.java
+++ b/services/core/java/com/android/server/input/InputDataStore.java
@@ -89,6 +89,10 @@ public final class InputDataStore {
final InputStream inputStream = mInputGestureFileInjector.openRead(userId);
inputGestureDataList = readInputGesturesXml(inputStream, false);
inputStream.close();
+ } catch (FileNotFoundException exception) {
+ // There are valid reasons for the file to be missing, such as shortcuts having not
+ // been registered by the user.
+ return List.of();
} catch (IOException exception) {
// In case we are unable to read from the file on disk or another IO operation error,
// fail gracefully.
diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS
index e507c6ba40a1..9d8aef943fa5 100644
--- a/services/core/java/com/android/server/inputmethod/OWNERS
+++ b/services/core/java/com/android/server/inputmethod/OWNERS
@@ -1,7 +1,6 @@
set noparent
roosa@google.com
-yukawa@google.com
tarandeep@google.com
fstern@google.com
cosminbaies@google.com
diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
index 463989adc98f..60d028b46970 100644
--- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
+++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
@@ -390,10 +390,11 @@ public class BackgroundInstallControlService extends SystemService {
.max(Comparator.comparingLong(PackageInstaller.SessionInfo::getCreatedMillis));
}
- // ADB sets installerPackageName to null, this creates a loophole to bypass BIC which will be
- // addressed with b/265203007
private boolean installedByAdb(String initiatingPackageName) {
- if(PackageManagerServiceUtils.isInstalledByAdb(initiatingPackageName)) {
+ // GTS tests needs to adopt shell identity to install apps.
+ if(!SystemProperties.get("gts.transparency.bg-install-apps").isEmpty()) {
+ Slog.d(TAG, "handlePackageAdd: is GTS tests, skipping ADB check");
+ } else if(PackageManagerServiceUtils.isInstalledByAdb(initiatingPackageName)) {
Slog.d(TAG, "handlePackageAdd: is installed by ADB, skipping");
return true;
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index f96846cdb2f4..acdc79fb9922 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -1067,6 +1067,9 @@ final class InstallPackageHelper {
void doPostDexopt(List<ReconciledPackage> reconciledPackages,
List<InstallRequest> requests, Map<String, Boolean> createdAppId,
MoveInfo moveInfo, long acquireTime) {
+ for (InstallRequest request : requests) {
+ request.onWaitDexoptFinished();
+ }
boolean success = false;
try {
if (commitInstallPackages(reconciledPackages)) {
@@ -1218,6 +1221,7 @@ final class InstallPackageHelper {
CompletableFuture<Void> future =
DexOptHelper.performDexoptIfNeededAsync(request, mDexManager);
completableFutures.add(future);
+ request.onWaitDexoptStarted();
}
if (!completableFutures.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index fbf5db5d9635..734920435e26 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -1028,6 +1028,18 @@ final class InstallRequest {
}
}
+ public void onWaitDexoptStarted() {
+ if (mPackageMetrics != null) {
+ mPackageMetrics.onStepStarted(PackageMetrics.STEP_WAIT_DEXOPT);
+ }
+ }
+
+ public void onWaitDexoptFinished() {
+ if (mPackageMetrics != null) {
+ mPackageMetrics.onStepFinished(PackageMetrics.STEP_WAIT_DEXOPT);
+ }
+ }
+
public void onDexoptFinished(DexoptResult dexoptResult) {
// Only report external profile warnings when installing from adb. The goal is to warn app
// developers if they have provided bad external profiles, so it's not beneficial to report
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 62b89f3252e6..f98ec04f84d8 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -1,7 +1,6 @@
hackbod@android.com
hackbod@google.com
jsharkey@android.com
-jsharkey@google.com
narayan@google.com
include /PACKAGE_MANAGER_OWNERS
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 136cb1259113..635ef069741b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -5189,7 +5189,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
"Session " + sessionId + " is a parent of multi-package session and "
+ "requestUserPreapproval on the parent session isn't supported.");
}
-
+ if (statusReceiver == null) {
+ throw new IllegalArgumentException("Status receiver cannot be null.");
+ }
synchronized (mLock) {
assertPreparedAndNotSealedLocked("request of session " + sessionId);
mPreapprovalDetails = details;
@@ -5542,6 +5544,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
*/
private static void sendOnUserActionRequired(Context context, IntentSender target,
int sessionId, Intent intent) {
+ if (target == null) {
+ Slog.e(TAG, "Missing receiver for pending user action.");
+ return;
+ }
final Intent fillIn = new Intent();
fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION);
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index 994ee421790c..22da3b2e7636 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -73,6 +73,7 @@ final class PackageMetrics {
public static final int STEP_DEXOPT = 5;
public static final int STEP_FREEZE_INSTALL = 6;
public static final int STEP_RESTORE = 7;
+ public static final int STEP_WAIT_DEXOPT = 8;
@IntDef(prefix = {"STEP_"}, value = {
STEP_PREPARE,
@@ -81,7 +82,8 @@ final class PackageMetrics {
STEP_COMMIT,
STEP_DEXOPT,
STEP_FREEZE_INSTALL,
- STEP_RESTORE
+ STEP_RESTORE,
+ STEP_WAIT_DEXOPT
})
@Retention(RetentionPolicy.SOURCE)
public @interface StepInt {
diff --git a/services/core/java/com/android/server/pm/dex/OWNERS b/services/core/java/com/android/server/pm/dex/OWNERS
index 5ca8ddd1fe17..70af4e7d36b2 100644
--- a/services/core/java/com/android/server/pm/dex/OWNERS
+++ b/services/core/java/com/android/server/pm/dex/OWNERS
@@ -1,4 +1,3 @@
-alanstokes@google.com
jiakaiz@google.com
ngeoffray@google.com
mast@google.com
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index e3eced252d1f..dd454cd61b2c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -7445,6 +7445,13 @@ public final class PowerManagerService extends SystemService
public void setDevicePostured(boolean isPostured) {
setDevicePosturedInternal(isPostured);
}
+
+ @Override
+ public void updateSettings() {
+ synchronized (mLock) {
+ updateSettingsLocked();
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/power/stats/BatteryHistoryDirectory.java b/services/core/java/com/android/server/power/stats/BatteryHistoryDirectory.java
index 29cc9ea13625..5563f98e8842 100644
--- a/services/core/java/com/android/server/power/stats/BatteryHistoryDirectory.java
+++ b/services/core/java/com/android/server/power/stats/BatteryHistoryDirectory.java
@@ -251,6 +251,10 @@ public class BatteryHistoryDirectory implements BatteryStatsHistory.BatteryHisto
try (FileInputStream stream = file.openRead()) {
byte[] header = new byte[FILE_FORMAT_BYTES];
if (stream.read(header, 0, FILE_FORMAT_BYTES) == -1) {
+ if (file.getBaseFile().length() == 0) {
+ return new byte[0];
+ }
+
Slog.e(TAG, "Invalid battery history file format " + file.getBaseFile());
deleteFragment(fragment);
return null;
diff --git a/services/core/java/com/android/server/uri/OWNERS b/services/core/java/com/android/server/uri/OWNERS
index cdc07ed7c67a..6599db7936c0 100644
--- a/services/core/java/com/android/server/uri/OWNERS
+++ b/services/core/java/com/android/server/uri/OWNERS
@@ -1,3 +1,2 @@
jsharkey@android.com
-jsharkey@google.com
varunshah@google.com
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 12f553426c80..58534b95bdde 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -712,13 +712,17 @@ final class AccessibilityController {
if (!isMagnifierActivated) {
return;
}
- // All opening/closing situations.
+ // All opening/closing/recents transitions
+ boolean notify = (flags & TRANSIT_FLAG_IS_RECENTS) != 0;
switch (type) {
case WindowManager.TRANSIT_OPEN:
case WindowManager.TRANSIT_TO_FRONT:
case WindowManager.TRANSIT_CLOSE:
case WindowManager.TRANSIT_TO_BACK:
- mUserContextChangedNotifier.onWMTransition(type, flags);
+ notify = true;
+ }
+ if (notify) {
+ mUserContextChangedNotifier.onWMTransition(type, flags);
}
}
@@ -1088,8 +1092,7 @@ final class AccessibilityController {
// causing the notifying, or the recents/home window is removed, then we won't need the
// delayed notification anymore.
void onWMTransition(@TransitionType int type, @TransitionFlags int flags) {
- if (type == WindowManager.TRANSIT_TO_FRONT
- && (flags & TRANSIT_FLAG_IS_RECENTS) != 0) {
+ if ((flags & TRANSIT_FLAG_IS_RECENTS) != 0) {
// Delay the recents to front transition notification then send after if needed.
mHasDelayedNotificationForRecentsToFrontTransition = true;
} else {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 247264f049d6..bdde5fe9dcb5 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -58,6 +58,7 @@ import static android.os.Process.INVALID_UID;
import static android.security.Flags.preventIntentRedirectAbortOrThrowException;
import static android.security.Flags.preventIntentRedirectShowToast;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_FLAG_AVOID_MOVE_TO_FRONT;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -1841,6 +1842,9 @@ class ActivityStarter {
// no-user-leaving implies not entering PiP.
transition.setCanPipOnFinish(false /* canPipOnFinish */);
}
+ if (avoidMoveToFront() && transition != null) {
+ transition.addFlag(TRANSIT_FLAG_AVOID_MOVE_TO_FRONT);
+ }
if (isIndependentLaunch && transition != null) {
transitionController.requestStartTransition(transition,
mTargetTask == null ? started.getTask() : mTargetTask,
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index f51e60c101e4..36686fc086f1 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -312,7 +312,6 @@ public class BackgroundActivityStartController {
private final @ActivityManager.ProcessState int mCallingUidProcState;
private final boolean mIsCallingUidPersistentSystemProcess;
final BackgroundStartPrivileges mBalAllowedByPiSender;
- final BackgroundStartPrivileges mBalAllowedByPiCreatorWithHardening;
final BackgroundStartPrivileges mBalAllowedByPiCreator;
private final String mRealCallingPackage;
private final int mRealCallingUid;
@@ -379,22 +378,14 @@ public class BackgroundActivityStartController {
if (mAutoOptInCaller) {
// grant BAL privileges unless explicitly opted out
- mBalAllowedByPiCreatorWithHardening = mBalAllowedByPiCreator =
+ mBalAllowedByPiCreator =
callerBackgroundActivityStartMode == MODE_BACKGROUND_ACTIVITY_START_DENIED
? BackgroundStartPrivileges.NONE
: BackgroundStartPrivileges.ALLOW_BAL;
} else {
// for PendingIntents we restrict BAL based on target_sdk
- mBalAllowedByPiCreatorWithHardening = getBackgroundStartPrivilegesAllowedByCreator(
+ mBalAllowedByPiCreator = getBackgroundStartPrivilegesAllowedByCreator(
callingUid, callingPackage, checkedOptions);
- final BackgroundStartPrivileges mBalAllowedByPiCreatorWithoutHardening =
- callerBackgroundActivityStartMode
- == MODE_BACKGROUND_ACTIVITY_START_DENIED
- ? BackgroundStartPrivileges.NONE
- : BackgroundStartPrivileges.ALLOW_BAL;
- mBalAllowedByPiCreator = balRequireOptInByPendingIntentCreator()
- ? mBalAllowedByPiCreatorWithHardening
- : mBalAllowedByPiCreatorWithoutHardening;
}
if (mAutoOptInReason != null) {
@@ -585,9 +576,8 @@ public class BackgroundActivityStartController {
if (mCallerApp != null) {
sb.append("; inVisibleTask: ").append(mCallerApp.hasActivityInVisibleTask());
}
- sb.append("; balAllowedByPiCreator: ").append(mBalAllowedByPiCreator);
- sb.append("; balAllowedByPiCreatorWithHardening: ")
- .append(mBalAllowedByPiCreatorWithHardening);
+ sb.append("; balAllowedByPiCreator: ")
+ .append(mBalAllowedByPiCreator);
if (mResultForCaller != null) {
sb.append("; resultIfPiCreatorAllowsBal: ")
.append(balCodeToString(mResultForCaller.mCode));
@@ -638,14 +628,13 @@ public class BackgroundActivityStartController {
}
static class BalVerdict {
- static final BalVerdict BLOCK = new BalVerdict(BAL_BLOCK, false, "Blocked");
+ static final BalVerdict BLOCK = new BalVerdict(BAL_BLOCK, "Blocked");
static final BalVerdict ALLOW_BY_DEFAULT =
- new BalVerdict(BAL_ALLOW_DEFAULT, false, "Default");
+ new BalVerdict(BAL_ALLOW_DEFAULT, "Default");
// Careful using this - it will bypass all ASM checks.
static final BalVerdict ALLOW_PRIVILEGED =
- new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID, false, "PRIVILEGED");
+ new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID, "PRIVILEGED");
private final @BalCode int mCode;
- private final boolean mBackground;
private final String mMessage;
private String mProcessInfo;
// indicates BAL would be blocked because only creator of the PI has the privilege to allow
@@ -654,8 +643,7 @@ public class BackgroundActivityStartController {
/** indicates that this verdict is based on the real calling UID and not the calling UID */
private boolean mBasedOnRealCaller;
- BalVerdict(@BalCode int balCode, boolean background, String message) {
- this.mBackground = background;
+ BalVerdict(@BalCode int balCode, String message) {
this.mCode = balCode;
this.mMessage = message;
}
@@ -708,16 +696,7 @@ public class BackgroundActivityStartController {
builder.append(" [realCaller]");
}
if (DEBUG_ACTIVITY_STARTS) {
- builder.append(" (");
- if (mBackground) {
- builder.append("Background ");
- }
- builder.append("Activity start ");
- if (mCode == BAL_BLOCK) {
- builder.append("denied");
- } else {
- builder.append("allowed: ").append(mMessage);
- }
+ builder.append(" (").append(mMessage);
if (mProcessInfo != null) {
builder.append(" ");
builder.append(mProcessInfo);
@@ -795,7 +774,6 @@ public class BackgroundActivityStartController {
// to realCallingUid when calculating resultForRealCaller below.
if (getService().hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
state.setResultForRealCaller(new BalVerdict(BAL_ALLOW_SDK_SANDBOX,
- /*background*/ false,
"uid in SDK sandbox has visible (non-toast) window"));
return allowBasedOnRealCaller(state);
}
@@ -1059,8 +1037,7 @@ public class BackgroundActivityStartController {
|| state.mAppSwitchState == APP_SWITCH_FG_ONLY
|| isHomeApp(state.mCallingUid, state.mCallingPackage);
if (appSwitchAllowedOrFg && state.mCallingUidHasVisibleActivity) {
- return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
- /*background*/ false, "callingUid has visible window");
+ return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "callingUid has visible window");
}
return BalVerdict.BLOCK;
};
@@ -1068,7 +1045,7 @@ public class BackgroundActivityStartController {
private final BalExemptionCheck mCheckCallerNonAppVisible = state -> {
if (state.mCallingUidHasNonAppVisibleWindow) {
return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
- /*background*/ false, "callingUid has non-app visible window "
+ "callingUid has non-app visible window "
+ getService().mActiveUids.getNonAppVisibleWindowDetails(state.mCallingUid));
}
return BalVerdict.BLOCK;
@@ -1080,9 +1057,7 @@ public class BackgroundActivityStartController {
if (state.mCallingUid == Process.ROOT_UID
|| callingAppId == Process.SYSTEM_UID
|| callingAppId == Process.NFC_UID) {
- return new BalVerdict(
- BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
- "Important callingUid");
+ return new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID, "Important callingUid");
}
return BalVerdict.BLOCK;
};
@@ -1090,9 +1065,7 @@ public class BackgroundActivityStartController {
private final BalExemptionCheck mCheckCallerIsAllowlistedComponent = state -> {
// Always allow home application to start activities.
if (isHomeApp(state.mCallingUid, state.mCallingPackage)) {
- return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ false,
- "Home app");
+ return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT, "Home app");
}
final int callingAppId = UserHandle.getAppId(state.mCallingUid);
@@ -1100,37 +1073,31 @@ public class BackgroundActivityStartController {
final WindowState imeWindow =
getService().mRootWindowContainer.getCurrentInputMethodWindow();
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
- return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ false,
- "Active ime");
+ return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT, "Active ime");
}
// don't abort if the callingUid is a persistent system process
if (state.mIsCallingUidPersistentSystemProcess) {
return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ false, "callingUid is persistent system process");
+ "callingUid is persistent system process");
}
// don't abort if the caller has the same uid as the recents component
if (getSupervisor().mRecentTasks.isCallerRecents(state.mCallingUid)) {
- return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ true, "Recents Component");
+ return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT, "Recents Component");
}
// don't abort if the callingUid is the device owner
if (getService().isDeviceOwner(state.mCallingUid)) {
- return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ true, "Device Owner");
+ return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT, "Device Owner");
}
// don't abort if the callingUid is a affiliated profile owner
if (getService().isAffiliatedProfileOwner(state.mCallingUid)) {
- return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ true, "Affiliated Profile Owner");
+ return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT, "Affiliated Profile Owner");
}
// don't abort if the callingUid has companion device
final int callingUserId = UserHandle.getUserId(state.mCallingUid);
if (getService().isAssociatedCompanionApp(callingUserId, state.mCallingUid)) {
- return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ true, "Companion App");
+ return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT, "Companion App");
}
return BalVerdict.BLOCK;
};
@@ -1139,7 +1106,6 @@ public class BackgroundActivityStartController {
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
if (hasBalPermission(state.mCallingUid, state.mCallingPid)) {
return new BalVerdict(BAL_ALLOW_PERMISSION,
- /*background*/ true,
"START_ACTIVITIES_FROM_BACKGROUND permission granted");
}
return BalVerdict.BLOCK;
@@ -1149,7 +1115,7 @@ public class BackgroundActivityStartController {
if (getService().hasSystemAlertWindowPermission(state.mCallingUid, state.mCallingPid,
state.mCallingPackage)) {
return new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
- /*background*/ true, "SYSTEM_ALERT_WINDOW permission is granted");
+ "SYSTEM_ALERT_WINDOW permission is granted");
}
return BalVerdict.BLOCK;
};
@@ -1159,7 +1125,7 @@ public class BackgroundActivityStartController {
if (isSystemExemptFlagEnabled() && getService().getAppOpsManager().checkOpNoThrow(
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
state.mCallingUid, state.mCallingPackage) == AppOpsManager.MODE_ALLOWED) {
- return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/ true,
+ return new BalVerdict(BAL_ALLOW_PERMISSION,
"OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
}
return BalVerdict.BLOCK;
@@ -1200,8 +1166,7 @@ public class BackgroundActivityStartController {
|| state.mAppSwitchState == APP_SWITCH_FG_ONLY
|| isHomeApp(state.mRealCallingUid, state.mRealCallingPackage);
if (appSwitchAllowedOrFg && state.mRealCallingUidHasVisibleActivity) {
- return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
- /*background*/ false, "realCallingUid has visible window");
+ return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "realCallingUid has visible window");
}
return BalVerdict.BLOCK;
};
@@ -1209,9 +1174,9 @@ public class BackgroundActivityStartController {
private final BalExemptionCheck mCheckRealCallerNonAppVisible = state -> {
if (state.mRealCallingUidHasNonAppVisibleWindow) {
return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
- /*background*/ false, "realCallingUid has non-app visible window "
- + getService().mActiveUids.getNonAppVisibleWindowDetails(
- state.mRealCallingUid));
+ "realCallingUid has non-app visible window "
+ + getService().mActiveUids.getNonAppVisibleWindowDetails(
+ state.mRealCallingUid));
}
return BalVerdict.BLOCK;
};
@@ -1230,9 +1195,7 @@ public class BackgroundActivityStartController {
== MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
if (allowAlways
&& hasBalPermission(state.mRealCallingUid, state.mRealCallingPid)) {
- return new BalVerdict(BAL_ALLOW_PERMISSION,
- /*background*/ false,
- "realCallingUid has BAL permission.");
+ return new BalVerdict(BAL_ALLOW_PERMISSION, "realCallingUid has BAL permission.");
}
return BalVerdict.BLOCK;
};
@@ -1245,7 +1208,7 @@ public class BackgroundActivityStartController {
&& getService().hasSystemAlertWindowPermission(state.mRealCallingUid,
state.mRealCallingPid, state.mRealCallingPackage)) {
return new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
- /*background*/ true, "SYSTEM_ALERT_WINDOW permission is granted");
+ "SYSTEM_ALERT_WINDOW permission is granted");
}
return BalVerdict.BLOCK;
};
@@ -1258,7 +1221,6 @@ public class BackgroundActivityStartController {
if ((allowAlways || state.mAllowBalExemptionForSystemProcess)
&& state.mIsRealCallingUidPersistentSystemProcess) {
return new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID,
- /*background*/ false,
"realCallingUid is persistent system process AND intent "
+ "sender forced to allow.");
}
@@ -1270,7 +1232,6 @@ public class BackgroundActivityStartController {
if (getService().isAssociatedCompanionApp(
UserHandle.getUserId(state.mRealCallingUid), state.mRealCallingUid)) {
return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
- /*background*/ false,
"realCallingUid is a companion app.");
}
return BalVerdict.BLOCK;
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index ccf1aedb3177..31b239421baf 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -125,27 +125,27 @@ class BackgroundLaunchProcessController {
long lastActivityFinishTime) {
// Allow if the proc is instrumenting with background activity starts privs.
if (checkConfiguration.checkOtherExemptions && hasBackgroundActivityStartPrivileges) {
- return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/ true,
+ return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/
"process instrumenting with background activity starts privileges");
}
// Allow if the flag was explicitly set.
if (checkConfiguration.checkOtherExemptions && isBackgroundStartAllowedByToken(uid,
packageName, checkConfiguration.isCheckingForFgsStart)) {
return new BalVerdict(balImprovedMetrics() ? BAL_ALLOW_TOKEN : BAL_ALLOW_PERMISSION,
- /*background*/ true, "process allowed by token");
+ /*background*/ "process allowed by token");
}
// Allow if the caller is bound by a UID that's currently foreground.
// But still respect the appSwitchState.
if (checkConfiguration.checkVisibility && appSwitchState != APP_SWITCH_DISALLOW
&& isBoundByForegroundUid()) {
return new BalVerdict(balImprovedMetrics() ? BAL_ALLOW_BOUND_BY_FOREGROUND
- : BAL_ALLOW_VISIBLE_WINDOW, /*background*/ false,
+ : BAL_ALLOW_VISIBLE_WINDOW, /*background*/
"process bound by foreground uid");
}
// Allow if the caller has an activity in any foreground task.
if (checkConfiguration.checkOtherExemptions && hasActivityInVisibleTask
&& appSwitchState != APP_SWITCH_DISALLOW) {
- return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ false,
+ return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/
"process has activity in foreground task");
}
@@ -160,7 +160,7 @@ class BackgroundLaunchProcessController {
long timeSinceLastStartOrFinish = now - Math.max(lastActivityLaunchTime,
lastActivityFinishTime);
if (timeSinceLastStartOrFinish < checkConfiguration.gracePeriod) {
- return new BalVerdict(BAL_ALLOW_GRACE_PERIOD, /*background*/ true,
+ return new BalVerdict(BAL_ALLOW_GRACE_PERIOD, /*background*/
"within " + checkConfiguration.gracePeriod + "ms grace period ("
+ timeSinceLastStartOrFinish + "ms)");
}
diff --git a/services/core/java/com/android/server/wm/ClientLifecycleManager.java b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
index d291d99f2a7a..98e453b3ff89 100644
--- a/services/core/java/com/android/server/wm/ClientLifecycleManager.java
+++ b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
@@ -25,6 +25,7 @@ import android.app.servertransaction.LaunchActivityItem;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.os.Build;
+import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
@@ -66,64 +67,80 @@ class ClientLifecycleManager {
/**
* Schedules a transaction, which may consist of multiple callbacks and a lifecycle request.
* @param transaction A sequence of client transaction items.
- * @throws RemoteException
- *
+ * @return {@code false} if the transaction failed because of {@link RemoteException}.
* @see ClientTransaction
*/
@VisibleForTesting
- void scheduleTransaction(@NonNull ClientTransaction transaction) throws RemoteException {
- final IApplicationThread client = transaction.getClient();
- try {
- transaction.schedule();
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to deliver transaction for " + client
- + "\ntransaction=" + transaction);
- throw e;
+ boolean scheduleTransaction(@NonNull ClientTransaction transaction) {
+ final RemoteException e = transaction.schedule();
+ if (e != null) {
+ final WindowProcessController wpc = mWms.mAtmService.getProcessController(
+ transaction.getClient());
+ Slog.w(TAG, "Failed to deliver transaction for " + wpc + "\ntransaction=" + this, e);
+ return false;
}
+ return true;
}
/**
* Similar to {@link #scheduleTransactionItem}, but it sends the transaction immediately and
* it can be called without WM lock.
*
+ * @return {@code false} if the transaction failed because of {@link RemoteException}.
* @see WindowProcessController#setReportedProcState(int)
*/
- void scheduleTransactionItemNow(@NonNull IApplicationThread client,
+ boolean scheduleTransactionItemNow(@NonNull IApplicationThread client,
@NonNull ClientTransactionItem transactionItem) throws RemoteException {
final ClientTransaction clientTransaction = new ClientTransaction(client);
clientTransaction.addTransactionItem(transactionItem);
- scheduleTransaction(clientTransaction);
+ final boolean res = scheduleTransaction(clientTransaction);
+ if (!com.android.window.flags.Flags.cleanupDispatchPendingTransactionsRemoteException()
+ && !res) {
+ throw new DeadObjectException();
+ }
+ return res;
}
/**
- * Schedules a transaction with the given item, delivery to client application.
+ * Schedules a transaction with the given item, delivery to client application, which may be
+ * queued to dispatched later.
*
- * @throws RemoteException
+ * @return {@code false} if the transaction was dispatched immediately, but failed because of
+ * {@link RemoteException}. If the transaction is queued, any failure will be ignored.
* @see ClientTransactionItem
*/
- void scheduleTransactionItem(@NonNull IApplicationThread client,
+ boolean scheduleTransactionItem(@NonNull IApplicationThread client,
@NonNull ClientTransactionItem item) throws RemoteException {
// Wait until RootWindowContainer#performSurfacePlacementNoTrace to dispatch all pending
// transactions at once.
final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client);
clientTransaction.addTransactionItem(item);
- onClientTransactionItemScheduled(clientTransaction, false /* shouldDispatchImmediately */);
+ final boolean res = onClientTransactionItemScheduled(clientTransaction,
+ false /* shouldDispatchImmediately */);
+ if (!com.android.window.flags.Flags.cleanupDispatchPendingTransactionsRemoteException()
+ && !res) {
+ throw new DeadObjectException();
+ }
+ return res;
}
/**
- * Schedules a transaction with the given items, delivery to client application.
+ * Schedules a transaction with the given items, delivery to client application, which may be
+ * queued to dispatched later.
*
- * @throws RemoteException
+ * @return {@code false} if the transaction was dispatched immediately, but failed because of
+ * {@link RemoteException}. If the transaction is queued, any failure will be ignored.
* @see ClientTransactionItem
*/
- void scheduleTransactionItems(@NonNull IApplicationThread client,
+ boolean scheduleTransactionItems(@NonNull IApplicationThread client,
@NonNull ClientTransactionItem... items) throws RemoteException {
- scheduleTransactionItems(client, false /* shouldDispatchImmediately */, items);
+ return scheduleTransactionItems(client, false /* shouldDispatchImmediately */, items);
}
/**
- * Schedules a transaction with the given items, delivery to client application.
+ * Schedules a transaction with the given items, delivery to client application, which may be
+ * queued to dispatched later.
*
* @param shouldDispatchImmediately whether or not to dispatch the transaction immediately. This
* should only be {@code true} when it is important to know the
@@ -131,11 +148,11 @@ class ClientLifecycleManager {
* launches an app, the server needs to know if the transaction
* is dispatched successfully, and may restart the process if
* not.
- *
- * @throws RemoteException
+ * @return {@code false} if the transaction was dispatched immediately, but failed because of
+ * {@link RemoteException}. If the transaction is queued, any failure will be ignored.
* @see ClientTransactionItem
*/
- void scheduleTransactionItems(@NonNull IApplicationThread client,
+ boolean scheduleTransactionItems(@NonNull IApplicationThread client,
boolean shouldDispatchImmediately,
@NonNull ClientTransactionItem... items) throws RemoteException {
// Wait until RootWindowContainer#performSurfacePlacementNoTrace to dispatch all pending
@@ -147,7 +164,13 @@ class ClientLifecycleManager {
clientTransaction.addTransactionItem(items[i]);
}
- onClientTransactionItemScheduled(clientTransaction, shouldDispatchImmediately);
+ final boolean res = onClientTransactionItemScheduled(clientTransaction,
+ shouldDispatchImmediately);
+ if (!com.android.window.flags.Flags.cleanupDispatchPendingTransactionsRemoteException()
+ && !res) {
+ throw new DeadObjectException();
+ }
+ return res;
}
/** Executes all the pending transactions. */
@@ -159,12 +182,7 @@ class ClientLifecycleManager {
final int size = mPendingTransactions.size();
for (int i = 0; i < size; i++) {
final ClientTransaction transaction = mPendingTransactions.valueAt(i);
- try {
- scheduleTransaction(transaction);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to deliver pending transaction", e);
- // TODO(b/323801078): apply cleanup for individual transaction item if needed.
- }
+ scheduleTransaction(transaction);
}
mPendingTransactions.clear();
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -174,12 +192,7 @@ class ClientLifecycleManager {
void dispatchPendingTransaction(@NonNull IApplicationThread client) {
final ClientTransaction pendingTransaction = mPendingTransactions.remove(client.asBinder());
if (pendingTransaction != null) {
- try {
- scheduleTransaction(pendingTransaction);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to deliver pending transaction", e);
- // TODO(b/323801078): apply cleanup for individual transaction item if needed.
- }
+ scheduleTransaction(pendingTransaction);
}
}
@@ -211,15 +224,22 @@ class ClientLifecycleManager {
return transaction;
}
- /** Must only be called with WM lock. */
- private void onClientTransactionItemScheduled(
+ /**
+ * Must only be called with WM lock.
+ * If the transaction should not be queued, it will be dispatched immediately.
+ *
+ * @return {@code false} if the transaction was dispatched immediately, but failed because of
+ * {@link RemoteException}.
+ */
+ private boolean onClientTransactionItemScheduled(
@NonNull ClientTransaction clientTransaction,
- boolean shouldDispatchImmediately) throws RemoteException {
+ boolean shouldDispatchImmediately) {
if (shouldDispatchImmediately || shouldDispatchPendingTransactionsImmediately()) {
// Dispatch the pending transaction immediately.
mPendingTransactions.remove(clientTransaction.getClient().asBinder());
- scheduleTransaction(clientTransaction);
+ return scheduleTransaction(clientTransaction);
}
+ return true;
}
/** Must only be called with WM lock. */
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index d6ae65193121..c26acec19743 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -490,7 +490,7 @@ final class ContentRecorder implements WindowContainerListener {
return null;
}
final Task taskToRecord = wc.asTask();
- if (taskToRecord == null) {
+ if (taskToRecord == null || !taskToRecord.isAttached()) {
handleStartRecordingFailed();
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
"Content Recording: Unable to retrieve task to start recording for "
diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
index 0106a64660fe..7a959c14fbd2 100644
--- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
+++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
@@ -52,6 +52,13 @@ public final class DesktopModeBoundsCalculator {
.getInt("persist.wm.debug.desktop_mode_landscape_app_padding", 25);
/**
+ * Proportion of window height top offset with respect to bottom offset, used for central task
+ * positioning. Should be kept in sync with constant in
+ * {@link com.android.wm.shell.desktopmode.DesktopTaskPosition}
+ */
+ public static final float WINDOW_HEIGHT_PROPORTION = 0.375f;
+
+ /**
* Updates launch bounds for an activity with respect to its activity options, window layout,
* android manifest and task configuration.
*/
@@ -63,7 +70,16 @@ public final class DesktopModeBoundsCalculator {
final Rect stableBounds = new Rect();
task.getDisplayArea().getStableRect(stableBounds);
- if (options != null && options.getLaunchBounds() != null) {
+ // If the options bounds size is flexible, update size with calculated desired size.
+ final boolean updateOptionBoundsSize = options != null
+ && options.getFlexibleLaunchSize();
+ // If cascading is also enabled, the position of the options bounds must be respected
+ // during the size update.
+ final boolean shouldRespectOptionPosition =
+ updateOptionBoundsSize && DesktopModeFlags.ENABLE_CASCADING_WINDOWS.isTrue();
+
+ if (options != null && options.getLaunchBounds() != null
+ && !updateOptionBoundsSize) {
outBounds.set(options.getLaunchBounds());
logger.accept("inherit-from-options=" + outBounds);
} else if (layout != null) {
@@ -76,26 +92,34 @@ public final class DesktopModeBoundsCalculator {
stableBounds);
logger.accept("layout specifies sizes, inheriting size and applying gravity");
} else if (verticalGravity > 0 || horizontalGravity > 0) {
- outBounds.set(calculateInitialBounds(task, activity, stableBounds));
+ outBounds.set(calculateInitialBounds(task, activity, stableBounds, options,
+ shouldRespectOptionPosition));
applyLayoutGravity(verticalGravity, horizontalGravity, outBounds,
stableBounds);
logger.accept("layout specifies gravity, applying desired bounds and gravity");
+ logger.accept("respecting option bounds cascaded position="
+ + shouldRespectOptionPosition);
}
} else {
- outBounds.set(calculateInitialBounds(task, activity, stableBounds));
+ outBounds.set(calculateInitialBounds(task, activity, stableBounds, options,
+ shouldRespectOptionPosition));
logger.accept("layout not specified, applying desired bounds");
+ logger.accept("respecting option bounds cascaded position="
+ + shouldRespectOptionPosition);
}
}
/**
* Calculates the initial bounds required for an application to fill a scale of the display
* bounds without any letterboxing. This is done by taking into account the applications
- * fullscreen size, aspect ratio, orientation and resizability to calculate an area this is
- * compatible with the applications previous configuration.
+ * fullscreen size, aspect ratio, orientation and resizability to calculate an area that is
+ * compatible with the applications previous configuration. These bounds are then cascaded to
+ * either the center or to a cascading position supplied by Shell via the option bounds.
*/
@NonNull
private static Rect calculateInitialBounds(@NonNull Task task,
- @NonNull ActivityRecord activity, @NonNull Rect stableBounds
+ @NonNull ActivityRecord activity, @NonNull Rect stableBounds,
+ @Nullable ActivityOptions options, boolean shouldRespectOptionPosition
) {
// Display bounds not taking into account insets.
final TaskDisplayArea displayArea = task.getDisplayArea();
@@ -172,6 +196,9 @@ public final class DesktopModeBoundsCalculator {
}
default -> idealSize;
};
+ if (shouldRespectOptionPosition) {
+ return respectShellCascading(initialSize, stableBounds, options.getLaunchBounds());
+ }
return centerInScreen(initialSize, screenBounds);
}
@@ -266,14 +293,65 @@ public final class DesktopModeBoundsCalculator {
* Adjusts bounds to be positioned in the middle of the screen.
*/
@NonNull
- private static Rect centerInScreen(@NonNull Size desiredSize,
+ static Rect centerInScreen(@NonNull Size desiredSize,
@NonNull Rect screenBounds) {
- // TODO(b/325240051): Position apps with bottom heavy offset
- final int heightOffset = (screenBounds.height() - desiredSize.getHeight()) / 2;
+ final int heightOffset = (int)
+ ((screenBounds.height() - desiredSize.getHeight()) * WINDOW_HEIGHT_PROPORTION);
final int widthOffset = (screenBounds.width() - desiredSize.getWidth()) / 2;
final Rect resultBounds = new Rect(0, 0,
desiredSize.getWidth(), desiredSize.getHeight());
resultBounds.offset(screenBounds.left + widthOffset, screenBounds.top + heightOffset);
return resultBounds;
}
+
+ /**
+ * Calculates final initial bounds based on the task's desired size and the cascading anchor
+ * point extracted from the option bounds. Cascading behaviour should be kept in sync with
+ * logic in {@link com.android.wm.shell.desktopmode.DesktopTaskPosition}.
+ */
+ @NonNull
+ private static Rect respectShellCascading(@NonNull Size desiredSize, @NonNull Rect stableBounds,
+ @NonNull Rect optionBounds) {
+ final boolean leftAligned = stableBounds.left == optionBounds.left;
+ final boolean rightAligned = stableBounds.right == optionBounds.right;
+ final boolean topAligned = stableBounds.top == optionBounds.top;
+ final boolean bottomAligned = stableBounds.bottom == optionBounds.bottom;
+ if (leftAligned && topAligned) {
+ // Bounds cascaded to top left, respect top left position anchor point.
+ return new Rect(
+ optionBounds.left,
+ optionBounds.top,
+ optionBounds.left + desiredSize.getWidth(),
+ optionBounds.top + desiredSize.getHeight()
+ );
+ }
+ if (leftAligned && bottomAligned) {
+ // Bounds cascaded to bottom left, respect bottom left position anchor point.
+ return new Rect(
+ optionBounds.left,
+ optionBounds.bottom - desiredSize.getHeight(),
+ optionBounds.left + desiredSize.getWidth(),
+ optionBounds.bottom
+ );
+ }
+ if (rightAligned && topAligned) {
+ // Bounds cascaded to top right, respect top right position anchor point.
+ return new Rect(
+ optionBounds.right - desiredSize.getWidth(),
+ optionBounds.top,
+ optionBounds.right,
+ optionBounds.top + desiredSize.getHeight()
+ );
+ }
+ if (rightAligned && bottomAligned) {
+ // Bounds cascaded to bottom right, respect bottom right position anchor point.
+ return new Rect(
+ optionBounds.right - desiredSize.getWidth(),
+ optionBounds.bottom - desiredSize.getHeight(),
+ optionBounds.right,
+ optionBounds.bottom);
+ }
+ // Bounds not cascaded to any corner, default to center position.
+ return centerInScreen(desiredSize, stableBounds);
+ }
}
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index a4eeb688162c..d466a646c7dd 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -42,6 +42,7 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
private static final String TAG =
TAG_WITH_CLASS_NAME ? "DesktopModeLaunchParamsModifier" : TAG_ATM;
+
private static final boolean DEBUG = false;
private StringBuilder mLogBuilder;
@@ -133,6 +134,14 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
DesktopModeBoundsCalculator.updateInitialBounds(task, layout, activity, options,
outParams.mBounds, this::appendLog);
appendLog("final desktop mode task bounds set to %s", outParams.mBounds);
+ if (options != null && options.getFlexibleLaunchSize()) {
+ // Return result done to prevent other modifiers from respecting option bounds and
+ // applying further cascading. Since other modifiers are being skipped in this case,
+ // this modifier is now also responsible to respecting the options launch windowing
+ // mode.
+ outParams.mWindowingMode = options.getLaunchWindowingMode();
+ return RESULT_DONE;
+ }
return RESULT_CONTINUE;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 64c19ff70c9f..574ab05075c4 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6575,6 +6575,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
.getKeyguardController().isKeyguardLocked(mDisplayId);
}
+ boolean isKeyguardLockedOrAodShowing() {
+ return isKeyguardLocked() || isAodShowing();
+ }
+
+ /**
+ * @return whether aod is showing for this display
+ */
+ boolean isAodShowing() {
+ final boolean isAodShowing = mRootWindowContainer.mTaskSupervisor
+ .getKeyguardController().isAodShowing(mDisplayId);
+ if (mDisplayId == DEFAULT_DISPLAY && isAodShowing) {
+ return !isKeyguardGoingAway();
+ }
+ return isAodShowing;
+ }
+
/**
* @return whether keyguard is going away on this display
*/
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 6d73739e5046..4eeed5ec8423 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
@@ -216,6 +217,9 @@ class KeyguardController {
} else if (keyguardShowing && !state.mKeyguardShowing) {
transition.addFlag(TRANSIT_FLAG_KEYGUARD_APPEARING);
}
+ if (mWindowManager.mFlags.mAodTransition && aodShowing && !state.mAodShowing) {
+ transition.addFlag(TRANSIT_FLAG_AOD_APPEARING);
+ }
}
}
// Update the task snapshot if the screen will not be turned off. To make sure that the
@@ -238,19 +242,28 @@ class KeyguardController {
state.mAodShowing = aodShowing;
state.writeEventLog("setKeyguardShown");
- if (keyguardChanged) {
- // Irrelevant to AOD.
- state.mKeyguardGoingAway = false;
- if (keyguardShowing) {
- state.mDismissalRequested = false;
+ if (keyguardChanged || (mWindowManager.mFlags.mAodTransition && aodChanged)) {
+ if (keyguardChanged) {
+ // Irrelevant to AOD.
+ state.mKeyguardGoingAway = false;
+ if (keyguardShowing) {
+ state.mDismissalRequested = false;
+ }
}
if (goingAwayRemoved
- || (keyguardShowing && !Display.isOffState(dc.getDisplayInfo().state))) {
+ || (keyguardShowing && !Display.isOffState(dc.getDisplayInfo().state))
+ || (mWindowManager.mFlags.mAodTransition && aodShowing)) {
// Keyguard decided to show or stopped going away. Send a transition to animate back
// to the locked state before holding the sleep token again
if (!ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS) {
- dc.requestTransitionAndLegacyPrepare(
- TRANSIT_TO_FRONT, TRANSIT_FLAG_KEYGUARD_APPEARING, /* trigger= */ null);
+ if (keyguardChanged) {
+ dc.requestTransitionAndLegacyPrepare(TRANSIT_TO_FRONT,
+ TRANSIT_FLAG_KEYGUARD_APPEARING, /* trigger= */ null);
+ }
+ if (mWindowManager.mFlags.mAodTransition && aodChanged && aodShowing) {
+ dc.requestTransitionAndLegacyPrepare(TRANSIT_TO_FRONT,
+ TRANSIT_FLAG_AOD_APPEARING, /* trigger= */ null);
+ }
}
dc.mWallpaperController.adjustWallpaperWindows();
dc.executeAppTransition();
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index dede7676a4b6..243a5326b545 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -3,7 +3,6 @@ set noparent
ogunwale@google.com
jjaggi@google.com
racarr@google.com
-chaviw@google.com
vishnun@google.com
akulian@google.com
roosa@google.com
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 3db1d50f3d6a..c78cdaa10df2 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -36,6 +36,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -980,6 +981,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
return false;
}
+ boolean isInAodAppearTransition() {
+ return (mFlags & TRANSIT_FLAG_AOD_APPEARING) != 0;
+ }
+
/**
* Specifies configuration change explicitly for the window container, so it can be chosen as
* transition target. This is usually used with transition mode
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 11c5c9345ab2..9b3b4451a746 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -526,6 +526,19 @@ class TransitionController {
return false;
}
+ boolean isInAodAppearTransition() {
+ if (mCollectingTransition != null && mCollectingTransition.isInAodAppearTransition()) {
+ return true;
+ }
+ for (int i = mWaitingTransitions.size() - 1; i >= 0; --i) {
+ if (mWaitingTransitions.get(i).isInAodAppearTransition()) return true;
+ }
+ for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
+ if (mPlayingTransitions.get(i).isInAodAppearTransition()) return true;
+ }
+ return false;
+ }
+
/**
* @return A pair of the transition and restore-behind target for the given {@param container}.
* @param container An ancestor of a transient-launch activity
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index a8b9fedcdc73..644417ec98e5 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -166,6 +166,14 @@ class WallpaperController {
mFindResults.setWallpaperTarget(w);
return false;
}
+ } else if (mService.mFlags.mAodTransition
+ && mDisplayContent.isKeyguardLockedOrAodShowing()) {
+ if (mService.mPolicy.isKeyguardHostWindow(w.mAttrs)
+ && w.mTransitionController.isInAodAppearTransition()) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Found aod transition wallpaper target: " + w);
+ mFindResults.setWallpaperTarget(w);
+ return true;
+ }
}
final boolean animationWallpaper = animatingContainer != null
@@ -678,7 +686,8 @@ class WallpaperController {
private WallpaperWindowToken getTokenForTarget(WindowState target) {
if (target == null) return null;
WindowState window = mFindResults.getTopWallpaper(
- target.canShowWhenLocked() && mService.isKeyguardLocked());
+ (target.canShowWhenLocked() && mService.isKeyguardLocked())
+ || (mService.mFlags.mAodTransition && mDisplayContent.isAodShowing()));
return window == null ? null : window.mToken.asWallpaperToken();
}
@@ -721,7 +730,9 @@ class WallpaperController {
if (mFindResults.wallpaperTarget == null && mFindResults.useTopWallpaperAsTarget) {
mFindResults.setWallpaperTarget(
- mFindResults.getTopWallpaper(mDisplayContent.isKeyguardLocked()));
+ mFindResults.getTopWallpaper(mService.mFlags.mAodTransition
+ ? mDisplayContent.isKeyguardLockedOrAodShowing()
+ : mDisplayContent.isKeyguardLocked()));
}
}
@@ -885,11 +896,17 @@ class WallpaperController {
if (mDisplayContent.mWmService.mFlags.mEnsureWallpaperInTransitions) {
visibleRequested = mWallpaperTarget != null && mWallpaperTarget.isVisibleRequested();
}
- updateWallpaperTokens(visibleRequested, mDisplayContent.isKeyguardLocked());
+ updateWallpaperTokens(visibleRequested,
+ mService.mFlags.mAodTransition
+ ? mDisplayContent.isKeyguardLockedOrAodShowing()
+ : mDisplayContent.isKeyguardLocked());
ProtoLog.v(WM_DEBUG_WALLPAPER,
"Wallpaper at display %d - visibility: %b, keyguardLocked: %b",
- mDisplayContent.getDisplayId(), visible, mDisplayContent.isKeyguardLocked());
+ mDisplayContent.getDisplayId(), visible,
+ mService.mFlags.mAodTransition
+ ? mDisplayContent.isKeyguardLockedOrAodShowing()
+ : mDisplayContent.isKeyguardLocked());
if (visible && mLastFrozen != mFindResults.isWallpaperTargetForLetterbox) {
mLastFrozen = mFindResults.isWallpaperTargetForLetterbox;
diff --git a/services/core/jni/stats/OWNERS b/services/core/jni/stats/OWNERS
index ab2d91adaeab..8d87925fbe45 100644
--- a/services/core/jni/stats/OWNERS
+++ b/services/core/jni/stats/OWNERS
@@ -1,5 +1,4 @@
jeffreyhuang@google.com
-jtnguyen@google.com
muhammadq@google.com
sharaieko@google.com
singhtejinder@google.com
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index aee32a0473a3..215d6ca964eb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3582,14 +3582,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@GuardedBy("getLockObject()")
private boolean maybeMigrateMemoryTaggingLocked(String backupId) {
- if (!Flags.setMtePolicyCoexistence()) {
- Slog.i(LOG_TAG, "Memory Tagging not migrated because coexistence "
- + "support is disabled.");
- return false;
- }
if (mOwners.isMemoryTaggingMigrated()) {
- // TODO: Remove log after Flags.setMtePolicyCoexistence full rollout.
- Slog.v(LOG_TAG, "Memory Tagging was previously migrated to policy engine.");
return false;
}
@@ -16354,7 +16347,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static <V> PolicyDefinition<V> getPolicyDefinitionForIdentifier(
@NonNull String identifier) {
Objects.requireNonNull(identifier);
- if (Flags.setMtePolicyCoexistence() && MEMORY_TAGGING_POLICY.equals(identifier)) {
+ if (MEMORY_TAGGING_POLICY.equals(identifier)) {
return (PolicyDefinition<V>) PolicyDefinition.MEMORY_TAGGING;
} else {
return (PolicyDefinition<V>) getPolicyDefinitionForRestriction(identifier);
@@ -23759,46 +23752,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
}
- if (Flags.setMtePolicyCoexistence()) {
- enforcePermission(MANAGE_DEVICE_POLICY_MTE, caller.getPackageName(),
- UserHandle.USER_ALL);
- } else {
- Preconditions.checkCallAuthorization(
- isDefaultDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
- }
+ enforcePermission(MANAGE_DEVICE_POLICY_MTE, caller.getPackageName(),
+ UserHandle.USER_ALL);
synchronized (getLockObject()) {
- if (Flags.setMtePolicyCoexistence()) {
- final EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(null,
- MANAGE_DEVICE_POLICY_MTE, callerPackageName, caller.getUserId());
- if (flags != DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY) {
- mDevicePolicyEngine.setGlobalPolicy(
- PolicyDefinition.MEMORY_TAGGING,
- admin,
- new IntegerPolicyValue(flags));
- } else {
- mDevicePolicyEngine.removeGlobalPolicy(
- PolicyDefinition.MEMORY_TAGGING,
- admin);
- }
+ final EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(null,
+ MANAGE_DEVICE_POLICY_MTE, callerPackageName, caller.getUserId());
+ if (flags != DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY) {
+ mDevicePolicyEngine.setGlobalPolicy(
+ PolicyDefinition.MEMORY_TAGGING,
+ admin,
+ new IntegerPolicyValue(flags));
} else {
- ActiveAdmin admin =
- getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked();
- if (admin != null) {
- final String memtagProperty = "arm64.memtag.bootctl";
- if (flags == DevicePolicyManager.MTE_ENABLED) {
- mInjector.systemPropertiesSet(memtagProperty, "memtag");
- } else if (flags == DevicePolicyManager.MTE_DISABLED) {
- mInjector.systemPropertiesSet(memtagProperty, "memtag-off");
- } else if (flags == DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY) {
- if (admin.mtePolicy != DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY) {
- mInjector.systemPropertiesSet(memtagProperty, "default");
- }
- }
- admin.mtePolicy = flags;
- saveSettingsLocked(caller.getUserId());
- }
+ mDevicePolicyEngine.removeGlobalPolicy(
+ PolicyDefinition.MEMORY_TAGGING,
+ admin);
}
DevicePolicyEventLogger.createEvent(DevicePolicyEnums.SET_MTE_POLICY)
@@ -23817,10 +23785,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()),
"Only system services can call setMtePolicyBySystem");
- if (!Flags.setMtePolicyCoexistence()) {
- throw new UnsupportedOperationException("System can not set MTE policy only");
- }
-
EnforcingAdmin admin = EnforcingAdmin.createSystemEnforcingAdmin(systemEntity);
if (policy != DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY) {
mDevicePolicyEngine.setGlobalPolicy(
@@ -23858,31 +23822,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public int getMtePolicy(String callerPackageName) {
final CallerIdentity caller = getCallerIdentity(callerPackageName);
- if (Flags.setMtePolicyCoexistence()) {
- enforcePermission(MANAGE_DEVICE_POLICY_MTE, caller.getPackageName(),
- UserHandle.USER_ALL);
- } else {
- Preconditions.checkCallAuthorization(
- isDefaultDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isSystemUid(caller));
- }
+ enforcePermission(MANAGE_DEVICE_POLICY_MTE, caller.getPackageName(),
+ UserHandle.USER_ALL);
synchronized (getLockObject()) {
- if (Flags.setMtePolicyCoexistence()) {
- final EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(null,
- MANAGE_DEVICE_POLICY_MTE, callerPackageName, caller.getUserId());
- final Integer policyFromAdmin = mDevicePolicyEngine.getGlobalPolicySetByAdmin(
- PolicyDefinition.MEMORY_TAGGING, admin);
- return (policyFromAdmin != null ? policyFromAdmin
- : DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY);
- } else {
- ActiveAdmin admin =
- getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked();
- return admin != null
- ? admin.mtePolicy
- : DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY;
- }
+ final EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(null,
+ MANAGE_DEVICE_POLICY_MTE, callerPackageName, caller.getUserId());
+ final Integer policyFromAdmin = mDevicePolicyEngine.getGlobalPolicySetByAdmin(
+ PolicyDefinition.MEMORY_TAGGING, admin);
+ return (policyFromAdmin != null ? policyFromAdmin
+ : DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
index caaf0964bb4e..6dfe08c1eb7e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
@@ -433,10 +433,8 @@ class OwnersData {
out.attributeBoolean(null, ATTR_RESET_PASSWORD_WITH_TOKEN_MIGRATED,
mResetPasswordWithTokenMigrated);
}
- if (Flags.setMtePolicyCoexistence()) {
- out.attributeBoolean(null, ATTR_MEMORY_TAGGING_MIGRATED,
- mMemoryTaggingMigrated);
- }
+ out.attributeBoolean(null, ATTR_MEMORY_TAGGING_MIGRATED,
+ mMemoryTaggingMigrated);
if (Flags.setKeyguardDisabledFeaturesCoexistence()) {
out.attributeBoolean(null, ATTR_SET_KEYGUARD_DISABLED_FEATURES_MIGRATED,
mSetKeyguardDisabledFeaturesMigrated);
@@ -514,8 +512,7 @@ class OwnersData {
mResetPasswordWithTokenMigrated = Flags.resetPasswordWithTokenCoexistence()
&& parser.getAttributeBoolean(null,
ATTR_RESET_PASSWORD_WITH_TOKEN_MIGRATED, false);
- mMemoryTaggingMigrated = Flags.setMtePolicyCoexistence()
- && parser.getAttributeBoolean(null,
+ mMemoryTaggingMigrated = parser.getAttributeBoolean(null,
ATTR_MEMORY_TAGGING_MIGRATED, false);
mSetKeyguardDisabledFeaturesMigrated =
Flags.setKeyguardDisabledFeaturesCoexistence()
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml
index 5fe5b237bdef..d6a685378d9e 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidTest.xml
@@ -18,6 +18,9 @@
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-instrumentation" />
+ <!-- Needed for reading the app files for the test artifacts -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="install-arg" value="-t" />
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceMockedTest.java
index 6ad3df1dd6f2..ac11216bdf0a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceMockedTest.java
@@ -102,11 +102,12 @@ import java.io.FileInputStream;
import java.io.IOException;
/**
- * Run as {@code atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest}
+ * Run as {@code atest
+ * FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceMockedTest}
*/
-public final class UserManagerServiceTest {
+public final class UserManagerServiceMockedTest {
- private static final String TAG = UserManagerServiceTest.class.getSimpleName();
+ private static final String TAG = UserManagerServiceMockedTest.class.getSimpleName();
/**
* Id for a simple user (that doesn't have profiles).
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
index 17d8882b487c..ea83825cd810 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java
@@ -571,6 +571,95 @@ public class AutoclickControllerTest {
assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isNotEqualTo(-1);
}
+ @Test
+ @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+ public void pauseButton_panelNotHovered_clickNotTriggeredWhenPaused() {
+ injectFakeMouseActionHoverMoveEvent();
+
+ // Pause autoclick and ensure the panel is not hovered.
+ AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class);
+ when(mockAutoclickTypePanel.isPaused()).thenReturn(true);
+ when(mockAutoclickTypePanel.isHovered()).thenReturn(false);
+ mController.mAutoclickTypePanel = mockAutoclickTypePanel;
+
+ // Send hover move event.
+ MotionEvent hoverMove = MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 100,
+ /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+ /* x= */ 30f,
+ /* y= */ 0f,
+ /* metaState= */ 0);
+ hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+ mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+
+ // Verify click is not triggered.
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isEqualTo(-1);
+ }
+
+ @Test
+ @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+ public void pauseButton_panelHovered_clickTriggeredWhenPaused() {
+ injectFakeMouseActionHoverMoveEvent();
+
+ // Pause autoclick and hover the panel.
+ AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class);
+ when(mockAutoclickTypePanel.isPaused()).thenReturn(true);
+ when(mockAutoclickTypePanel.isHovered()).thenReturn(true);
+ mController.mAutoclickTypePanel = mockAutoclickTypePanel;
+
+ // Send hover move event.
+ MotionEvent hoverMove = MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 100,
+ /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+ /* x= */ 30f,
+ /* y= */ 0f,
+ /* metaState= */ 0);
+ hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+ mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+
+ // Verify click is triggered.
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isNotEqualTo(-1);
+ }
+
+ @Test
+ @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR)
+ public void pauseButton_unhoveringCancelsClickWhenPaused() {
+ injectFakeMouseActionHoverMoveEvent();
+
+ // Pause autoclick and hover the panel.
+ AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class);
+ when(mockAutoclickTypePanel.isPaused()).thenReturn(true);
+ when(mockAutoclickTypePanel.isHovered()).thenReturn(true);
+ mController.mAutoclickTypePanel = mockAutoclickTypePanel;
+
+ // Send hover move event.
+ MotionEvent hoverMove = MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 100,
+ /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+ /* x= */ 30f,
+ /* y= */ 0f,
+ /* metaState= */ 0);
+ hoverMove.setSource(InputDevice.SOURCE_MOUSE);
+ mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0);
+
+ // Verify click is triggered.
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isTrue();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isNotEqualTo(-1);
+
+ // Now simulate the pointer being moved outside the panel.
+ when(mockAutoclickTypePanel.isHovered()).thenReturn(false);
+ mController.clickPanelController.onHoverChange(/* hovered= */ false);
+
+ // Verify pending click is canceled.
+ assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse();
+ assertThat(mController.mClickScheduler.getScheduledClickTimeForTesting()).isEqualTo(-1);
+ }
+
private void injectFakeMouseActionHoverMoveEvent() {
MotionEvent event = getFakeMotionHoverMoveEvent();
event.setSource(InputDevice.SOURCE_MOUSE);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickLinearLayoutTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickLinearLayoutTest.java
new file mode 100644
index 000000000000..9e629f7c87a2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickLinearLayoutTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.autoclick;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.view.MotionEvent;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Test cases for {@link AutoclickLinearLayout}. */
+@RunWith(AndroidTestingRunner.class)
+public class AutoclickLinearLayoutTest {
+ private boolean mHovered;
+
+ private final AutoclickLinearLayout.OnHoverChangedListener mListener =
+ new AutoclickLinearLayout.OnHoverChangedListener() {
+ @Override
+ public void onHoverChanged(boolean hovered) {
+ mHovered = hovered;
+ }
+ };
+
+ @Rule
+ public TestableContext mTestableContext =
+ new TestableContext(getInstrumentation().getContext());
+ private AutoclickLinearLayout mAutoclickLinearLayout;
+
+ @Before
+ public void setUp() {
+ mAutoclickLinearLayout = new AutoclickLinearLayout(mTestableContext);
+ }
+
+ @Test
+ public void autoclickLinearLayout_hoverChangedListener_setHovered() {
+ mHovered = false;
+ mAutoclickLinearLayout.setOnHoverChangedListener(mListener);
+ mAutoclickLinearLayout.onHoverChanged(/* hovered= */ true);
+ assertThat(mHovered).isTrue();
+ }
+
+ @Test
+ public void autoclickLinearLayout_hoverChangedListener_setNotHovered() {
+ mHovered = true;
+
+ mAutoclickLinearLayout.setOnHoverChangedListener(mListener);
+ mAutoclickLinearLayout.onHoverChanged(/* hovered= */ false);
+ assertThat(mHovered).isFalse();
+ }
+
+ @Test
+ public void autoclickLinearLayout_onInterceptHoverEvent_hovered() {
+ mAutoclickLinearLayout.setHovered(false);
+ mAutoclickLinearLayout.onInterceptHoverEvent(
+ getFakeMotionEvent(MotionEvent.ACTION_HOVER_ENTER));
+ assertThat(mAutoclickLinearLayout.isHovered()).isTrue();
+
+ mAutoclickLinearLayout.setHovered(false);
+ mAutoclickLinearLayout.onInterceptHoverEvent(
+ getFakeMotionEvent(MotionEvent.ACTION_HOVER_MOVE));
+ assertThat(mAutoclickLinearLayout.isHovered()).isTrue();
+ }
+
+ @Test
+ public void autoclickLinearLayout_onInterceptHoverEvent_hoveredExit() {
+ mAutoclickLinearLayout.setHovered(true);
+ mAutoclickLinearLayout.onInterceptHoverEvent(
+ getFakeMotionEvent(MotionEvent.ACTION_HOVER_EXIT));
+ assertThat(mAutoclickLinearLayout.isHovered()).isFalse();
+ }
+
+ private MotionEvent getFakeMotionEvent(int motionEventAction) {
+ return MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 0,
+ /* action= */ motionEventAction,
+ /* x= */ 0,
+ /* y= */ 0,
+ /* metaState= */ 0);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
index 9e123406dff5..f7b16c808c50 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
@@ -78,6 +78,7 @@ public class AutoclickTypePanelTest {
private @AutoclickType int mActiveClickType = AUTOCLICK_TYPE_LEFT_CLICK;
private boolean mPaused;
+ private boolean mHovered;
private final ClickPanelControllerInterface clickPanelController =
new ClickPanelControllerInterface() {
@@ -90,6 +91,11 @@ public class AutoclickTypePanelTest {
public void toggleAutoclickPause(boolean paused) {
mPaused = paused;
}
+
+ @Override
+ public void onHoverChange(boolean hovered) {
+ mHovered = hovered;
+ }
};
@Before
@@ -412,6 +418,33 @@ public class AutoclickTypePanelTest {
upEvent.recycle();
}
+ @Test
+ public void hovered_IsHovered() {
+ AutoclickLinearLayout mContext = mAutoclickTypePanel.getContentViewForTesting();
+
+ assertThat(mAutoclickTypePanel.isHovered()).isFalse();
+ mContext.onInterceptHoverEvent(getFakeMotionHoverMoveEvent());
+ assertThat(mAutoclickTypePanel.isHovered()).isTrue();
+ }
+
+ @Test
+ public void hovered_OnHoverChange_isHovered() {
+ AutoclickLinearLayout mContext = mAutoclickTypePanel.getContentViewForTesting();
+
+ mHovered = false;
+ mContext.onHoverChanged(true);
+ assertThat(mHovered).isTrue();
+ }
+
+ @Test
+ public void hovered_OnHoverChange_isNotHovered() {
+ AutoclickLinearLayout mContext = mAutoclickTypePanel.getContentViewForTesting();
+
+ mHovered = true;
+ mContext.onHoverChanged(false);
+ assertThat(mHovered).isFalse();
+ }
+
private void verifyButtonHasSelectedStyle(@NonNull LinearLayout button) {
GradientDrawable gradientDrawable = (GradientDrawable) button.getBackground();
assertThat(gradientDrawable.getColor().getDefaultColor())
@@ -426,4 +459,14 @@ public class AutoclickTypePanelTest {
assertThat(params.x).isEqualTo(expectedPosition[2]);
assertThat(params.y).isEqualTo(expectedPosition[3]);
}
+
+ private MotionEvent getFakeMotionHoverMoveEvent() {
+ return MotionEvent.obtain(
+ /* downTime= */ 0,
+ /* eventTime= */ 0,
+ /* action= */ MotionEvent.ACTION_HOVER_MOVE,
+ /* x= */ 0,
+ /* y= */ 0,
+ /* metaState= */ 0);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpSqlPersistenceTest.java b/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpSqlPersistenceTest.java
index 84713079c9d3..01fee7f66497 100644
--- a/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpSqlPersistenceTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/DiscreteAppOpSqlPersistenceTest.java
@@ -226,9 +226,9 @@ public class DiscreteAppOpSqlPersistenceTest {
mDiscreteRegistry.recordDiscreteAccess(event2);
}
- /** This clears in-memory cache and push records into the database. */
private void flushDiscreteOpsToDatabase() {
- mDiscreteRegistry.writeAndClearOldAccessHistory();
+ // This clears in-memory cache and push records from cache into the database.
+ mDiscreteRegistry.shutdown();
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/appop/DiscreteOpsMigrationAndRollbackTest.java b/services/tests/servicestests/src/com/android/server/appop/DiscreteOpsMigrationAndRollbackTest.java
index 21cc3bac3938..8eea1c73d4f2 100644
--- a/services/tests/servicestests/src/com/android/server/appop/DiscreteOpsMigrationAndRollbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/DiscreteOpsMigrationAndRollbackTest.java
@@ -106,7 +106,8 @@ public class DiscreteOpsMigrationAndRollbackTest {
opEvent.getDuration(), opEvent.getAttributionFlags(),
(int) opEvent.getChainId(), DiscreteOpsRegistry.ACCESS_TYPE_NOTE_OP);
}
- sqlRegistry.writeAndClearOldAccessHistory();
+ // flush records from cache to the database.
+ sqlRegistry.shutdown();
assertThat(sqlRegistry.getAllDiscreteOps().size()).isEqualTo(RECORD_COUNT);
assertThat(sqlRegistry.getLargestAttributionChainId()).isEqualTo(RECORD_COUNT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 301a7544227f..9d4fe9e9765b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -41,8 +41,8 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.pm.ApplicationInfo.CATEGORY_SOCIAL;
import static android.content.pm.ApplicationInfo.CATEGORY_GAME;
+import static android.content.pm.ApplicationInfo.CATEGORY_SOCIAL;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.UI_MODE_TYPE_DESK;
@@ -66,7 +66,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -196,7 +195,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Because the booted state is set, avoid starting real home if there is no task.
doReturn(false).when(mRootWindowContainer).resumeHomeActivity(any(), anyString(), any());
// Do not execute the transaction, because we can't verify the parameter after it recycles.
- doNothing().when(mClientLifecycleManager).scheduleTransaction(any());
+ doReturn(true).when(mClientLifecycleManager).scheduleTransaction(any());
}
private TestStartingWindowOrganizer registerTestStartingWindowOrganizer() {
@@ -266,7 +265,7 @@ public class ActivityRecordTests extends WindowTestsBase {
break;
}
}
- return null;
+ return true;
}).when(mClientLifecycleManager).scheduleTransaction(any());
activity.setState(STOPPED, "testPausingWhenVisibleFromStopped");
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java
index c934c55dfb8e..e3a8776aca6a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java
@@ -486,7 +486,7 @@ public class BackgroundActivityStartControllerExemptionTests {
// setup state
when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
- new BalVerdict(BAL_ALLOW_FOREGROUND, false, "allowed"));
+ new BalVerdict(BAL_ALLOW_FOREGROUND, "allowed"));
when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
// prepare call
@@ -523,7 +523,7 @@ public class BackgroundActivityStartControllerExemptionTests {
mCallerApp);
when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW);
when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
- new BalVerdict(BAL_ALLOW_FOREGROUND, false, "allowed"));
+ new BalVerdict(BAL_ALLOW_FOREGROUND, "allowed"));
// prepare call
PendingIntentRecord originatingPendingIntent = mPendingIntentRecord;
@@ -572,7 +572,7 @@ public class BackgroundActivityStartControllerExemptionTests {
when(mCallerApp.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
BalVerdict.BLOCK);
when(otherProcess.areBackgroundActivityStartsAllowed(anyInt(), any())).thenReturn(
- new BalVerdict(BAL_ALLOW_FOREGROUND, false, "allowed"));
+ new BalVerdict(BAL_ALLOW_FOREGROUND, "allowed"));
// prepare call
PendingIntentRecord originatingPendingIntent = mPendingIntentRecord;
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerLogTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerLogTests.java
index 99e730ae76cf..cd5f3912bfc6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerLogTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerLogTests.java
@@ -92,7 +92,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void intent_visible_noLog() {
useIntent();
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false, "visible");
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "visible");
mState.setResultForCaller(finalVerdict);
mState.setResultForRealCaller(BalVerdict.BLOCK);
assertThat(mController.shouldLogStats(finalVerdict, mState)).isFalse();
@@ -101,7 +101,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void intent_saw_log() {
useIntent();
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, false, "SAW");
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, "SAW");
mState.setResultForCaller(finalVerdict);
mState.setResultForRealCaller(BalVerdict.BLOCK);
assertThat(mController.shouldLogStats(finalVerdict, mState)).isTrue();
@@ -111,7 +111,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void pendingIntent_callerOnly_saw_log() {
usePendingIntent();
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, false, "SAW");
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, "SAW");
mState.setResultForCaller(finalVerdict);
mState.setResultForRealCaller(BalVerdict.BLOCK);
assertThat(mController.shouldLogStats(finalVerdict, mState)).isTrue();
@@ -121,7 +121,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void pendingIntent_realCallerOnly_saw_log() {
usePendingIntent();
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, false, "SAW")
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, "SAW")
.setBasedOnRealCaller();
mState.setResultForCaller(BalVerdict.BLOCK);
mState.setResultForRealCaller(finalVerdict);
@@ -131,7 +131,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void intent_shouldLogIntentActivity() {
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, false, "SAW");
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, "SAW");
useIntent(APP1_UID);
assertThat(mController.shouldLogIntentActivity(finalVerdict, mState)).isFalse();
useIntent(SYSTEM_UID);
@@ -140,7 +140,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void pendingIntent_shouldLogIntentActivityForCaller() {
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, false, "SAW");
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, "SAW");
usePendingIntent(APP1_UID, APP2_UID);
assertThat(mController.shouldLogIntentActivity(finalVerdict, mState)).isFalse();
usePendingIntent(SYSTEM_UID, SYSTEM_UID);
@@ -153,7 +153,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void pendingIntent_shouldLogIntentActivityForRealCaller() {
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION, false,
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
"SAW").setBasedOnRealCaller();
usePendingIntent(APP1_UID, APP2_UID);
assertThat(mController.shouldLogIntentActivity(finalVerdict, mState)).isFalse();
@@ -168,7 +168,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void pendingIntent_realCallerOnly_visible_noLog() {
usePendingIntent();
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false,
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
"visible").setBasedOnRealCaller();
mState.setResultForCaller(BalVerdict.BLOCK);
mState.setResultForRealCaller(finalVerdict);
@@ -178,7 +178,7 @@ public class BackgroundActivityStartControllerLogTests {
@Test
public void pendingIntent_callerOnly_visible_noLog() {
usePendingIntent();
- BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false, "visible");
+ BalVerdict finalVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "visible");
mState.setResultForCaller(finalVerdict);
mState.setResultForRealCaller(BalVerdict.BLOCK);
assertThat(mController.shouldLogStats(finalVerdict, mState)).isTrue();
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
index 51706d72cb35..fe9a6e746513 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java
@@ -305,7 +305,7 @@ public class BackgroundActivityStartControllerTests {
@Test
public void testRegularActivityStart_allowedByCaller_isAllowed() {
// setup state
- BalVerdict callerVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false,
+ BalVerdict callerVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
"CallerIsVisible");
mController.setCallerVerdict(callerVerdict);
mController.setRealCallerVerdict(BalVerdict.BLOCK);
@@ -340,7 +340,7 @@ public class BackgroundActivityStartControllerTests {
@Test
public void testRegularActivityStart_allowedByRealCaller_isAllowed() {
// setup state
- BalVerdict realCallerVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false,
+ BalVerdict realCallerVerdict = new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
"RealCallerIsVisible");
mController.setCallerVerdict(BalVerdict.BLOCK);
mController.setRealCallerVerdict(realCallerVerdict);
@@ -373,9 +373,9 @@ public class BackgroundActivityStartControllerTests {
public void testRegularActivityStart_allowedByCallerAndRealCaller_returnsCallerVerdict() {
// setup state
BalVerdict callerVerdict =
- new BalVerdict(BAL_ALLOW_PERMISSION, false, "CallerHasPermission");
+ new BalVerdict(BAL_ALLOW_PERMISSION, "CallerHasPermission");
BalVerdict realCallerVerdict =
- new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false, "RealCallerIsVisible");
+ new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "RealCallerIsVisible");
mController.setCallerVerdict(callerVerdict);
mController.setRealCallerVerdict(realCallerVerdict);
@@ -411,9 +411,9 @@ public class BackgroundActivityStartControllerTests {
public void testPendingIntent_allowedByCallerAndRealCallerButOptOut_isBlocked() {
// setup state
BalVerdict callerVerdict =
- new BalVerdict(BAL_ALLOW_PERMISSION, false, "CallerhasPermission");
+ new BalVerdict(BAL_ALLOW_PERMISSION, "CallerhasPermission");
BalVerdict realCallerVerdict =
- new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false, "RealCallerIsVisible");
+ new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "RealCallerIsVisible");
mController.setCallerVerdict(callerVerdict);
mController.setRealCallerVerdict(realCallerVerdict);
@@ -452,7 +452,7 @@ public class BackgroundActivityStartControllerTests {
public void testPendingIntent_allowedByCallerAndOptIn_isAllowed() {
// setup state
BalVerdict callerVerdict =
- new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false, "CallerIsVisible");
+ new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "CallerIsVisible");
mController.setCallerVerdict(callerVerdict);
mController.setRealCallerVerdict(BalVerdict.BLOCK);
@@ -489,7 +489,7 @@ public class BackgroundActivityStartControllerTests {
public void testPendingIntent_allowedByRealCallerAndOptIn_isAllowed() {
// setup state
BalVerdict realCallerVerdict =
- new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, false, "RealCallerIsVisible");
+ new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, "RealCallerIsVisible");
mController.setCallerVerdict(BalVerdict.BLOCK);
mController.setRealCallerVerdict(realCallerVerdict);
@@ -571,7 +571,6 @@ public class BackgroundActivityStartControllerTests {
+ "callerApp: mCallerApp; "
+ "inVisibleTask: false; "
+ "balAllowedByPiCreator: BSP.ALLOW_BAL; "
- + "balAllowedByPiCreatorWithHardening: BSP.ALLOW_BAL; "
+ "callerStartMode: MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; "
+ "hasRealCaller: true; "
+ "isCallForResult: false; "
@@ -674,7 +673,6 @@ public class BackgroundActivityStartControllerTests {
+ "callerApp: mCallerApp; "
+ "inVisibleTask: false; "
+ "balAllowedByPiCreator: BSP.NONE; "
- + "balAllowedByPiCreatorWithHardening: BSP.NONE; "
+ "callerStartMode: MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; "
+ "hasRealCaller: true; "
+ "isCallForResult: false; "
diff --git a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
index 02ad9dbfda8e..8d214dd2c940 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
@@ -16,11 +16,13 @@
package com.android.server.wm;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -32,17 +34,19 @@ import android.app.IApplicationThread;
import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
+import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
+import com.android.window.flags.Flags;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -60,15 +64,11 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
@Mock
private IApplicationThread mClient;
@Mock
- private IApplicationThread.Stub mNonBinderClient;
- @Mock
private ClientTransaction mTransaction;
@Mock
private ClientTransactionItem mTransactionItem;
@Mock
private ActivityLifecycleItem mLifecycleItem;
- @Captor
- private ArgumentCaptor<ClientTransaction> mTransactionCaptor;
private WindowManagerService mWms;
private ClientLifecycleManager mLifecycleManager;
@@ -83,7 +83,6 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
doReturn(true).when(mLifecycleItem).isActivityLifecycleItem();
doReturn(mClientBinder).when(mClient).asBinder();
- doReturn(mNonBinderClient).when(mNonBinderClient).asBinder();
}
@Test
@@ -91,13 +90,11 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
spyOn(mWms.mWindowPlacerLocked);
doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
- // Use non binder client to get non-recycled ClientTransaction.
- mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mTransactionItem);
+ mLifecycleManager.scheduleTransactionItem(mClient, mTransactionItem);
// When there is traversal scheduled, add transaction items to pending.
assertEquals(1, mLifecycleManager.mPendingTransactions.size());
- ClientTransaction transaction =
- mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+ ClientTransaction transaction = mLifecycleManager.mPendingTransactions.get(mClientBinder);
assertEquals(1, transaction.getTransactionItems().size());
assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
// TODO(b/324203798): cleanup after remove UnsupportedAppUsage
@@ -108,10 +105,10 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
// Add new transaction item to the existing pending.
clearInvocations(mLifecycleManager);
- mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mLifecycleItem);
+ mLifecycleManager.scheduleTransactionItem(mClient, mLifecycleItem);
assertEquals(1, mLifecycleManager.mPendingTransactions.size());
- transaction = mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+ transaction = mLifecycleManager.mPendingTransactions.get(mClientBinder);
assertEquals(2, transaction.getTransactionItems().size());
assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
assertEquals(mLifecycleItem, transaction.getTransactionItems().get(1));
@@ -124,8 +121,7 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
@Test
public void testScheduleTransactionItemNow() throws RemoteException {
- // Use non binder client to get non-recycled ClientTransaction.
- mLifecycleManager.scheduleTransactionItemNow(mNonBinderClient, mTransactionItem);
+ mLifecycleManager.scheduleTransactionItemNow(mClient, mTransactionItem);
// Dispatch immediately.
assertTrue(mLifecycleManager.mPendingTransactions.isEmpty());
@@ -137,13 +133,11 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
spyOn(mWms.mWindowPlacerLocked);
doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
- // Use non binder client to get non-recycled ClientTransaction.
- mLifecycleManager.scheduleTransactionItems(mNonBinderClient, mTransactionItem,
- mLifecycleItem);
+ mLifecycleManager.scheduleTransactionItems(mClient, mTransactionItem, mLifecycleItem);
assertEquals(1, mLifecycleManager.mPendingTransactions.size());
final ClientTransaction transaction =
- mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+ mLifecycleManager.mPendingTransactions.get(mClientBinder);
assertEquals(2, transaction.getTransactionItems().size());
assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
assertEquals(mLifecycleItem, transaction.getTransactionItems().get(1));
@@ -160,8 +154,8 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
spyOn(mWms.mWindowPlacerLocked);
doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
- // Use non binder client to get non-recycled ClientTransaction.
- mLifecycleManager.scheduleTransactionItems(mNonBinderClient,
+ mLifecycleManager.scheduleTransactionItems(
+ mClient,
true /* shouldDispatchImmediately */,
mTransactionItem, mLifecycleItem);
@@ -187,7 +181,7 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
doReturn(true).when(mWms.mWindowPlacerLocked).isLayoutDeferred();
// Queue transactions during layout deferred.
- mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mLifecycleItem);
+ mLifecycleManager.scheduleTransactionItem(mClient, mLifecycleItem);
verify(mLifecycleManager, never()).scheduleTransaction(any());
@@ -203,4 +197,42 @@ public class ClientLifecycleManagerTests extends SystemServiceTestsBase {
verify(mLifecycleManager).scheduleTransaction(any());
}
+
+ @EnableFlags(Flags.FLAG_CLEANUP_DISPATCH_PENDING_TRANSACTIONS_REMOTE_EXCEPTION)
+ @Test
+ public void testOnRemoteException_returnTrueOnSuccess() throws RemoteException {
+ final boolean res = mLifecycleManager.scheduleTransactionItemNow(mClient, mTransactionItem);
+
+ assertTrue(res);
+ }
+
+ @EnableFlags(Flags.FLAG_CLEANUP_DISPATCH_PENDING_TRANSACTIONS_REMOTE_EXCEPTION)
+ @Test
+ public void testOnRemoteException_returnFalseOnFailure() throws RemoteException {
+ final DeadObjectException e = new DeadObjectException();
+ doThrow(e).when(mClient).scheduleTransaction(any());
+
+ // No exception when flag enabled.
+ final boolean res = mLifecycleManager.scheduleTransactionItemNow(mClient, mTransactionItem);
+
+ assertFalse(res);
+ }
+
+ @EnableFlags(Flags.FLAG_CLEANUP_DISPATCH_PENDING_TRANSACTIONS_REMOTE_EXCEPTION)
+ @Test
+ public void testOnRemoteException_returnTrueForQueueing() throws RemoteException {
+ spyOn(mWms.mWindowPlacerLocked);
+ doReturn(true).when(mWms.mWindowPlacerLocked).isLayoutDeferred();
+ final DeadObjectException e = new DeadObjectException();
+ doThrow(e).when(mClient).scheduleTransaction(any());
+
+ final boolean res = mLifecycleManager.scheduleTransactionItem(mClient, mTransactionItem);
+
+ assertTrue(res);
+
+ doReturn(false).when(mWms.mWindowPlacerLocked).isLayoutDeferred();
+ mLifecycleManager.onLayoutContinued();
+
+ verify(mLifecycleManager).scheduleTransaction(any());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index 3a06fff1d1a7..bc37496d14a7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -42,8 +42,10 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_INITIAL_BOUNDS_SCALE;
import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_LANDSCAPE_APP_PADDING;
+import static com.android.server.wm.DesktopModeBoundsCalculator.centerInScreen;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
import static org.junit.Assert.assertEquals;
@@ -60,6 +62,7 @@ import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
+import android.util.Size;
import android.view.Gravity;
import androidx.test.filters.SmallTest;
@@ -1099,6 +1102,110 @@ public class DesktopModeLaunchParamsModifierTests extends
}
@Test
+ @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
+ Flags.FLAG_ENABLE_SHELL_INITIAL_BOUNDS_REGRESSION_BUG_FIX})
+ public void testOptionsBoundsSet_flexibleLaunchSize_windowingModeSet() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_STANDARD).setDisplay(display).build();
+ final ActivityOptions options = ActivityOptions.makeBasic()
+ .setLaunchBounds(new Rect(
+ DISPLAY_STABLE_BOUNDS.left,
+ DISPLAY_STABLE_BOUNDS.top,
+ /* right = */ 500,
+ /* bottom = */ 500))
+ .setFlexibleLaunchSize(true);
+ options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ assertEquals(RESULT_DONE,
+ new CalculateRequestBuilder().setTask(task).setOptions(options).calculate());
+ assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode);
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
+ Flags.FLAG_ENABLE_SHELL_INITIAL_BOUNDS_REGRESSION_BUG_FIX})
+ public void testOptionsBoundsSet_flexibleLaunchSize_boundsSizeModified() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_STANDARD).setDisplay(display).build();
+ final ActivityOptions options = ActivityOptions.makeBasic()
+ .setLaunchBounds(new Rect(
+ DISPLAY_STABLE_BOUNDS.left,
+ DISPLAY_STABLE_BOUNDS.top,
+ /* right = */ 500,
+ /* bottom = */ 500))
+ .setFlexibleLaunchSize(true);
+ final int modifiedWidth =
+ (int) (DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int modifiedHeight =
+ (int) (DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+
+ assertEquals(RESULT_DONE,
+ new CalculateRequestBuilder().setTask(task).setOptions(options).calculate());
+ assertEquals(modifiedWidth, mResult.mBounds.width());
+ assertEquals(modifiedHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
+ Flags.FLAG_ENABLE_SHELL_INITIAL_BOUNDS_REGRESSION_BUG_FIX})
+ public void testOptionsBoundsSet_flexibleLaunchSizeWithCascading_cornerCascadeRespected() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_STANDARD).setDisplay(display).build();
+ // Set launch bounds with corner cascade.
+ final ActivityOptions options = ActivityOptions.makeBasic()
+ .setLaunchBounds(new Rect(
+ DISPLAY_STABLE_BOUNDS.left,
+ DISPLAY_STABLE_BOUNDS.top,
+ /* right = */ 500,
+ /* bottom = */ 500))
+ .setFlexibleLaunchSize(true);
+
+ assertEquals(RESULT_DONE,
+ new CalculateRequestBuilder().setTask(task).setOptions(options).calculate());
+ assertEquals(DISPLAY_STABLE_BOUNDS.left, mResult.mBounds.left);
+ assertEquals(DISPLAY_STABLE_BOUNDS.top, mResult.mBounds.top);
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
+ Flags.FLAG_ENABLE_SHELL_INITIAL_BOUNDS_REGRESSION_BUG_FIX})
+ public void testOptionsBoundsSet_flexibleLaunchSize_centerCascadeRespected() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
+ final Task task = new TaskBuilder(mSupervisor).setActivityType(
+ ACTIVITY_TYPE_STANDARD).setDisplay(display).build();
+ // Set launch bounds with center cascade.
+ final ActivityOptions options = ActivityOptions.makeBasic()
+ .setLaunchBounds(new Rect(
+ /* left = */ 320,
+ /* top = */ 100,
+ /* right = */ 640,
+ /* bottom = */ 200))
+ .setFlexibleLaunchSize(true);
+ final int modifiedWidth =
+ (int) (DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int modifiedHeight =
+ (int) (DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final Rect centerCascadedBounds = centerInScreen(
+ new Size(modifiedWidth, modifiedHeight), DISPLAY_STABLE_BOUNDS);
+
+ assertEquals(RESULT_DONE,
+ new CalculateRequestBuilder().setTask(task).setOptions(options).calculate());
+ assertEquals(centerCascadedBounds, mResult.mBounds);
+ assertEquals(centerCascadedBounds.top, mResult.mBounds.top);
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testNonEmptyLayoutBounds_CenterToDisplay() {
setupDesktopModeLaunchParamsModifier();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index d228970e0371..9dc70266bf3d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -24,7 +24,6 @@ import static android.content.res.Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -295,7 +294,7 @@ public class WindowProcessControllerTests extends WindowTestsBase {
@Test
public void testCachedStateConfigurationChange() throws RemoteException {
- doNothing().when(mClientLifecycleManager).scheduleTransactionItemNow(any(), any());
+ doReturn(true).when(mClientLifecycleManager).scheduleTransactionItemNow(any(), any());
final IApplicationThread thread = mWpc.getThread();
final Configuration newConfig = new Configuration(mWpc.getConfiguration());
newConfig.densityDpi += 100;
diff --git a/telecomm/java/android/telecom/OWNERS b/telecomm/java/android/telecom/OWNERS
index 6656a01403b8..0854c5d45603 100644
--- a/telecomm/java/android/telecom/OWNERS
+++ b/telecomm/java/android/telecom/OWNERS
@@ -3,4 +3,3 @@
rgreenwalt@google.com
tgunn@google.com
breadley@google.com
-hallliu@google.com
diff --git a/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java b/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java
index 1bdf019d6c42..9d87fbd67eef 100644
--- a/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java
+++ b/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java
@@ -18,10 +18,12 @@ package android.app.jank.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import android.app.jank.Flags;
import android.app.jank.JankTracker;
import android.app.jank.StateTracker;
+import android.content.Context;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -55,10 +57,9 @@ public class JankTrackerTest {
* Start an empty activity so decore view is not null when creating the JankTracker instance.
*/
private static ActivityScenario<EmptyActivity> sEmptyActivityRule;
-
private static String sActivityName;
-
private static View sActivityDecorView;
+ private static Context sContext;
@BeforeClass
public static void classSetup() {
@@ -66,6 +67,7 @@ public class JankTrackerTest {
sEmptyActivityRule.onActivity(activity -> {
sActivityDecorView = activity.getWindow().getDecorView();
sActivityName = activity.toString();
+ sContext = activity.getApplicationContext();
});
}
@@ -168,4 +170,14 @@ public class JankTrackerTest {
assertNotNull(jankTracker);
}
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
+ public void jankTracker_IsNull_WhenViewNotInHierarchy() {
+ TestWidget testWidget = new TestWidget(sContext);
+ JankTracker jankTracker = testWidget.getJankTracker();
+
+ assertNull(jankTracker);
+ }
+
}
diff --git a/tests/EnforcePermission/OWNERS b/tests/EnforcePermission/OWNERS
index 39550a394f33..160849e5616f 100644
--- a/tests/EnforcePermission/OWNERS
+++ b/tests/EnforcePermission/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 315013
tweek@google.com
-brufino@google.com
diff --git a/tools/codegen/OWNERS b/tools/codegen/OWNERS
index c9bd260ca7ae..e69de29bb2d1 100644
--- a/tools/codegen/OWNERS
+++ b/tools/codegen/OWNERS
@@ -1 +0,0 @@
-chiuwinson@google.com
diff --git a/tools/hiddenapi/OWNERS b/tools/hiddenapi/OWNERS
index dc82aac9d41c..d1e36b953e7f 100644
--- a/tools/hiddenapi/OWNERS
+++ b/tools/hiddenapi/OWNERS
@@ -1,6 +1,5 @@
# compat-team@ for changes to hiddenapi files
mathewi@google.com
-satayev@google.com
# soong-team@ as the files these tools protect are tightly coupled with Soong
file:platform/build/soong:/OWNERS
diff --git a/tools/lint/OWNERS b/tools/lint/OWNERS
index 8e4569ee2a30..4035e19158c6 100644
--- a/tools/lint/OWNERS
+++ b/tools/lint/OWNERS
@@ -1,6 +1,5 @@
mattgilbride@google.com
azharaa@google.com
-jsharkey@google.com
per-file *CallingSettingsNonUserGetterMethods* = file:/packages/SettingsProvider/OWNERS
per-file *RegisterReceiverFlagDetector* = jacobhobbie@google.com
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS b/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS
index 2a4acc111257..abb9aa4c05a2 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 1216021
asapperstein@google.com
-etancohen@google.com